Setup

library(ggplot2)
library(dplyr)
library(tidyr)
library(purrr)
source("/home/guestA/n70275b/work/rscripts/geomNorm.R")

# Helper function
#ggpoints <- function(x,...) 
#  ggplot(x,...) + geom_point(size=3,stroke=1) +
#  ggrepel::geom_text_repel(size=4) + theme_minimal() + mycolor

## ラベルあり
ggpoints <- function(x,...) 
  ggplot(x,...) + geom_point(stroke=1) +
  ggrepel::geom_text_repel(size=4) + theme_minimal() + mycolor

## ラベルなし
#ggpoints <- function(x,...) 
#  ggplot(x,...) + geom_point(stroke=1) + theme_minimal() + mycolor


print(Sys.Date())
[1] "2020-09-15"
print(sessionInfo(),locale=FALSE)
R version 4.0.1 (2020-06-06)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Red Hat Enterprise Linux

Matrix products: default
BLAS/LAPACK: /usr/local/intel2018_up1/compilers_and_libraries_2018.0.128/linux/mkl/lib/intel64_lin/libmkl_intel_lp64.so

attached base packages:
 [1] grid      stats4    parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] corrplot_0.84                             Hmisc_4.4-1                               Formula_1.2-3                             survival_3.2-3                           
 [5] lattice_0.20-41                           stringr_1.4.0                             hrbrthemes_0.8.0                          ggrepel_0.8.2                            
 [9] ggpubr_0.4.0.999                          gplots_3.0.4                              DESeq2_1.28.1                             GGally_2.0.0                             
[13] vcd_1.4-7                                 BiocParallel_1.22.0                       Matrix_1.2-18                             SummarizedExperiment_1.18.2              
[17] DelayedArray_0.14.1                       matrixStats_0.56.0                        motifmatchr_1.10.0                        org.Mm.eg.db_3.11.4                      
[21] TxDb.Mmusculus.UCSC.mm10.knownGene_3.10.0 org.Hs.eg.db_3.11.4                       TxDb.Hsapiens.UCSC.hg19.knownGene_3.2.2   GenomicFeatures_1.40.1                   
[25] AnnotationDbi_1.50.3                      Biobase_2.48.0                            ChIPseeker_1.24.0                         clusterProfiler_3.16.1                   
[29] BSgenome.Mmusculus.UCSC.mm10_1.4.0        ggsignif_0.6.0                            chromVAR_1.10.0                           purrr_0.3.4                              
[33] RColorBrewer_1.1-2                        ggsci_2.9                                 readr_1.3.1                               tidyr_1.1.2                              
[37] dplyr_1.0.2                               ggplot2_3.3.2                             TFBSTools_1.26.0                          BSgenome_1.56.0                          
[41] rtracklayer_1.48.0                        Biostrings_2.56.0                         XVector_0.28.0                            GenomicRanges_1.40.0                     
[45] GenomeInfoDb_1.24.2                       IRanges_2.22.2                            S4Vectors_0.26.1                          BiocGenerics_0.34.0                      

loaded via a namespace (and not attached):
  [1] rappdirs_0.3.1              R.methodsS3_1.8.1           bit64_4.0.5                 knitr_1.29                  irlba_2.3.3                 R.utils_2.10.1             
  [7] rpart_4.1-15                data.table_1.13.0           KEGGREST_1.28.0             RCurl_1.98-1.2              generics_0.0.2              cowplot_1.1.0              
 [13] lambda.r_1.2.4              RSQLite_2.2.0               europepmc_0.4               bit_4.0.4                   enrichplot_1.8.1            xml2_1.3.2                 
 [19] httpuv_1.5.4                assertthat_0.2.1            DirichletMultinomial_1.30.0 viridis_0.5.1               xfun_0.17                   hms_0.5.3                  
 [25] evaluate_0.14               promises_1.1.1              fansi_0.4.1                 progress_1.2.2              caTools_1.18.0              dbplyr_1.4.4               
 [31] readxl_1.3.1                igraph_1.2.5                DBI_1.1.0                   geneplotter_1.66.0          htmlwidgets_1.5.1           futile.logger_1.4.3        
 [37] reshape_0.8.8               ellipsis_0.3.1              backports_1.1.9             annotate_1.66.0             biomaRt_2.44.1              vctrs_0.3.4                
 [43] abind_1.4-5                 withr_2.2.0                 ggforce_0.3.2               triebeard_0.3.0             checkmate_2.0.0             GenomicAlignments_1.24.0   
 [49] prettyunits_1.1.1           cluster_2.1.0               DOSE_3.14.0                 lazyeval_0.2.2              seqLogo_1.54.3              crayon_1.3.4               
 [55] genefilter_1.70.0           labeling_0.3                pkgconfig_2.0.3             tweenr_1.0.1                nlme_3.1-149                nnet_7.3-14                
 [61] rlang_0.4.7                 lifecycle_0.2.0             miniUI_0.1.1.1              downloader_0.4              extrafontdb_1.0             BiocFileCache_1.12.1       
 [67] cellranger_1.1.0            polyclip_1.10-0             lmtest_0.9-38               urltools_1.7.3              carData_3.0-4               boot_1.3-25                
 [73] zoo_1.8-8                   base64enc_0.1-3             pheatmap_1.0.12             ggridges_0.5.2              png_0.1-7                   viridisLite_0.3.0          
 [79] bitops_1.0-6                R.oo_1.24.0                 KernSmooth_2.23-17          blob_1.2.1                  qvalue_2.20.0               jpeg_0.1-8.1               
 [85] rstatix_0.6.0               gridGraphics_0.5-0          CNEr_1.24.0                 scales_1.1.1                memoise_1.1.0               magrittr_1.5               
 [91] plyr_1.8.6                  gdata_2.18.0                zlibbioc_1.34.0             compiler_4.0.1              scatterpie_0.1.5            plotrix_3.7-8              
 [97] Rsamtools_2.4.0             cli_2.0.2                   htmlTable_2.0.1             formatR_1.7                 mgcv_1.8-33                 MASS_7.3-53                
[103] tidyselect_1.1.0            stringi_1.5.3               forcats_0.5.0               yaml_2.2.1                  GOSemSim_2.14.2             askpass_1.1                
[109] locfit_1.5-9.4              latticeExtra_0.6-29         fastmatch_1.1-0             tools_4.0.1                 rio_0.5.16                  rstudioapi_0.11            
[115] TFMPvalue_0.0.8             foreign_0.8-80              gridExtra_2.3               farver_2.0.3                ggraph_2.0.3                digest_0.6.25              
[121] rvcheck_0.1.8               BiocManager_1.30.10         FNN_1.1.3                   shiny_1.5.0                 pracma_2.2.9                Rcpp_1.0.5                 
[127] car_3.0-9                   broom_0.7.0                 later_1.1.0.1               gdtools_0.2.2               httr_1.4.2                  colorspace_1.4-1           
[133] XML_3.99-0.5                splines_4.0.1               uwot_0.1.8                  graphlayouts_0.7.0          ggplotify_0.0.5             systemfonts_0.3.1          
[139] plotly_4.9.2.1              xtable_1.8-4                jsonlite_1.7.1              futile.options_1.0.1        poweRlaw_0.70.6             tidygraph_1.2.0            
[145] R6_2.4.1                    pillar_1.4.6                htmltools_0.5.0             mime_0.9                    cpp11_0.2.1                 glue_1.4.2                 
[151] fastmap_1.0.1               DT_0.15                     fgsea_1.14.0                utf8_1.1.4                  tibble_3.0.3                curl_4.3                   
[157] gtools_3.8.2                zip_2.1.1                   GO.db_3.11.4                openxlsx_4.1.5              openssl_1.4.2               Rttf2pt1_1.3.8             
[163] rmarkdown_2.3               munsell_0.5.0               DO.db_2.9                   GenomeInfoDbData_1.2.3      msigdbr_7.1.1               haven_2.3.1                
[169] reshape2_1.4.4              gtable_0.3.0                extrafont_0.17             
select <- dplyr::select
rename <- dplyr::rename #191203
count <- dplyr::count #191203

Parameters

modify here

# Files

deftable <- "/home/guestA/o70578a/akuwakado/kuwakado/scCELSeq2/Iwasaki_0386_C2C12_H3mm18/Final_Last_Rserver_200523/iwasaki_0386_noumi_def_fin191203__200523ver.txt" #最終版 121203


#deftable <- "/home/guestA/o70578a/akuwakado/kuwakado/scCELSeq2/Iwasaki_0386_C2C12_H3mm18/iwasaki_0386_umi_def_fin191203ver.txt" #最終版 121203
#deftable <- "/home/guestA/o70578a/akuwakado/kuwakado/scCELSeq2/Iwasaki_0386_C2C12_H3mm18/iwasaki_0386_umi_def.txt"

#deftable <- "deftable_BRB_umi_new.txt"

## Data selection (filter rows of deftable)
#use <- quo(!grepl("^18",group) & (group != "Nc-minusTryd"))
#use <- quo(TRUE) # use all
use <-  quo(group %in% c("eGFP_G","mm18B_G","eGFP_D72", "mm18B_D72"))
#use <- quo(type == "C2C12")
#use <- quo(type != "C2C12")
#use <- quo(TRUE)

#use <- quo(type == "Whole_cell")
#use <- quo(type == "Nucleus")

# Species specific parameters
species <- "Mus musculus"
biomartann <- "mmusculus_gene_ensembl"
maxchrom <- 19 # 19: mouse, 22: human

# Graphics
# aesthetic mapping of labels
#myaes <- aes(colour=enzyme,shape=leg,label=rep) 

#myaes <- aes(colour=growth,shape=type,size=count) #ラベルなし
#myaes <- aes(colour=growth,shape=type,label=replicate,size=count) #ラベルあり
#myaes <- aes(colour=enzyme,shape=leg,label=replicate) #ラベルあり
#myaes <- aes(colour=enzyme,shape=leg,label=factor(rep))

#myaes <- aes(colour=type,shape=trypsin,label=factor(lot)) 
#myaes <- aes(colour=trypsin,label=factor(lot)) 
myaes <- aes(colour=time,shape=type,label=factor(lot)) 

# color palette of points: See vignette("ggsci")
#mycolor <- ggsci::scale_color_aaas()
mycolor <- ggsci::scale_color_d3("category20") # color palette of points

# PCA/UMAP
scalerows <- TRUE # gene-wise scaling (pattern is the matter?)
ntop <- 500 # number of top-n genes with high variance
seed <- 123 # set another number if UMAP looks not good
n_nei <- 2  #6 # number of neighboring data points in UMAP

#hashigushi
scalerows <- FALSE # gene-wise scaling (pattern is the matter?)
#seed <- 123 # set another number if tSNE looks not good
#perprexity <- 3 # expected cluster size in tSNE

# DESeq2
#model <- ~type+trypsin

#model <- ~trypsin
model <- ~group


fdr <- 0.1 # acceptable false discovery rate
lfcthreth <- log2(1) # threshold in abs(log2FC)
# controls should be placed in the right
contrast <- list( 
  
  #time_D72_vs_G = c("time", "D72", "G")
  


  #group_G_H3f3b_vs_WT = c("group", "H3f3b_G", "WT_G"),
  #group_G_mm18B_vs_WT = c("group", "mm18B_G", "WT_G"),
  #group_G_eGFP_vs_WT = c("group", "eGFP_G", "WT_G"),
  #group_G_H3f3b_vs_eGFP = c("group", "H3f3b_G", "eGFP_G"),
  group_G_mm18B_vs_eGFP = c("group", "mm18B_G", "eGFP_G"),
  #group_G_mm18B_vs_H3f3b = c("group", "mm18B_G", "H3f3b_G"),
  
  #group_D72_H3f3b_vs_WT = c("group", "H3f3b_D72", "WT_D72"),
  #group_D72_mm18B_vs_WT = c("group", "mm18B_D72", "WT_D72"),
  #group_D72_eGFP_vs_WT = c("group", "eGFP_D72", "WT_D72"),
  #group_D72_H3f3b_vs_eGFP = c("group", "H3f3b_D72", "eGFP_D72"),
  group_D72_mm18B_vs_eGFP = c("group", "mm18B_D72", "eGFP_D72"),
  #group_D72_mm18B_vs_H3f3b = c("group", "mm18B_D72", "H3f3b_D72")
  
    #group_WT_D72_vs_G = c("group", "WT_D72", "WT_G"),
  group_eGFP_D72_vs_G = c("group", "eGFP_D72", "eGFP_G"),  
  #group_H3f3b_D72_vs_G = c("group", "H3f3b_D72", "H3f3b_G"),
  group_mm18B_D72_vs_G = c("group", "mm18B_D72", "mm18B_G")
  

  
  #type = c("type", "Nucleus", "Whole_cell"),
  #trypsin = c("trypsin", "plus", "untreated")
  
  #Intercept = list("Intercept"), # reference level
  #leg_LvsR = c("leg", "L", "R"),
  #enz_KvsC = c("enzyme","K","C")
  #legL.enzK = list("legL.enzymeK") # interaction
  
  #type_Doxplus_vs_minus = c("type", "Doxplus", "Doxminus")
)

Retrieve Biomart

if(!exists("e2g")){
  ensembl <- biomaRt::useMart("ENSEMBL_MART_ENSEMBL",host="asia.ensembl.org")
  #ensembl <- biomaRt::useMart("ENSEMBL_MART_ENSEMBL",host="uswest.ensembl.org")
  #ensembl <- biomaRt::useMart("ENSEMBL_MART_ENSEMBL",host="useast.ensembl.org")
  mart <- biomaRt::useDataset(biomartann,mart=ensembl)
  e2g <- biomaRt::getBM(attributes=c("ensembl_gene_id","external_gene_name",
    "gene_biotype","chromosome_name"), mart=mart) %>% as_tibble %>%
  rename(
    ens_gene = ensembl_gene_id,
    ext_gene = external_gene_name,
    biotype = gene_biotype,
    chr = chromosome_name
  )
}
annotate <- partial(right_join,e2g,by="ens_gene")

#-----#
nrow(e2g)
[1] 56305
readr::write_csv(e2g,"ensemble_list_asia__fin200915.csv")
#readr::write_csv(e2g,"ensemble_list_uswest_fin200523.csv.csv")
##readr::write_csv(e2g,"ensemble_list_useast.csv")

#e2g <- readr::read_csv("/home/guestA/o70578a/akuwakado/kuwakado/scCELSeq2/Iwasaki_0386_C2C12_H3mm18/Final_Last_Rserver_200523/ensemble_list_uswest_fin200523.csv.csv")
#annotate <- partial(right_join,e2g,by="ens_gene")
#nrow(e2g)

Load counts


def <- readr::read_tsv(deftable) %>% filter(!!use) %>% arrange(group,sample) #20200915 change
Parsed with column specification:
cols(
  RunSampleID = col_character(),
  SampleNo = col_character(),
  file = col_character(),
  sample = col_character(),
  primer = col_double(),
  i7indexID = col_character(),
  index = col_character(),
  flocell = col_character(),
  lane = col_character(),
  il_barcode = col_character(),
  day = col_double(),
  type = col_character(),
  time = col_character(),
  lot = col_character(),
  barcode = col_character(),
  group = col_character()
)
print(def)
readr::write_csv(def,"deftable_used_CEL0386noumi_C2C12_fin200915.csv")

####--- New ---#### (no UMI ?)
# Set reference levels according to the contrast
for(x in keep(contrast,is.character))
  def[[x[1]]] <- relevel(factor(def[[x[1]]]),x[3])

umi <- def$file %>% unique %>% tibble(file=.) %>% 
  dplyr::mutate(data=map(file,readr::read_tsv,progress=FALSE)) %>%
  unnest() %>% dplyr::rename(barcode=cell) %>%
  dplyr::inner_join(select(def,file,barcode,sample),.,c("file","barcode")) %>%
  select(-file,-barcode) %>% dplyr::rename(ens_gene=gene)
Parsed with column specification:
cols(
  gene = col_character(),
  cell = col_character(),
  count = col_double()
)
Parsed with column specification:
cols(
  gene = col_character(),
  cell = col_character(),
  count = col_double()
)
Parsed with column specification:
cols(
  gene = col_character(),
  cell = col_character(),
  count = col_double()
)
`cols` is now required when using unnest().
Please use `cols = c(data)`
print(umi)

## sample, barcode, file を忘れずに!

mat <- umi %>% annotate %>%
  dplyr::mutate(chr=factor(chr,c(1:maxchrom,"X","Y","MT"))) %>%
  filter(!is.na(chr)) %>% spread(sample,count,fill=0)
## to check read vias, this add read number as "n" column (2019/4/19)
def <- umi %>% count(sample,wt=count) %>% dplyr::inner_join(def,.) %>% dplyr::rename(count=n)
Joining, by = "sample"
####-----------#### 


#def <- readr::read_tsv(deftable) %>% filter(!!use)

####--- New ---#### (no UMI ?)
# Set reference levels according to the contrast
#for(x in keep(contrast,is.character))
#  def[[x[1]]] <- relevel(factor(def[[x[1]]]),x[3])

#umi <- def$file %>% unique %>% tibble(file=.) %>% 
#  dplyr::mutate(data=map(file,readr::read_tsv,progress=FALSE)) %>%
#  unnest() %>% dplyr::rename(barcode=cell) %>%
#  inner_join(select(def,file,barcode,sample),.,c("file","barcode")) %>%
#  select(-file,-barcode) %>% dplyr::rename(ens_gene=gene)

## sample, barcode, file を忘れずに!

#mat <- umi %>% annotate %>%
#  dplyr::mutate(chr=factor(chr,c(1:maxchrom,"X","Y","MT"))) %>%
#  filter(!is.na(chr)) %>% spread(sample,count,fill=0)
## to check read vias, this add read number as "n" column (2019/4/19)
#def <- umi %>% count(sample,wt=count) %>% inner_join(def,.) %>% dplyr::rename(count=n)
####-----------#### 

# Old
# Set reference levels according to the contrast
#for(x in keep(contrast,is.character))
#  def[[x[1]]] <- relevel(factor(def[[x[1]]]),x[3])
#umi <- def$file %>% unique %>% tibble(file=.) %>% 
#  mutate(data=map(file,readr::read_tsv,progress=FALSE)) %>%
#  unnest() %>% rename(barcode=cell) %>%
#  inner_join(select(def,file,barcode,sample),.,c("file","barcode")) %>%
#  select(-file,-barcode) %>% rename(ens_gene=gene)
#mat <- umi %>% annotate %>%
#  mutate(chr=factor(chr,c(1:maxchrom,"X","Y","MT"))) %>%
#  filter(!is.na(chr)) %>% spread(sample,count,fill=0)



print(umi)
print(def)

Reads breakdown

Total reads


bychr <- mat %>% select(-(1:3)) %>%
  gather("sample","count",-chr) %>%
  group_by(chr,sample) %>% summarise(total=sum(count)) %>% ungroup
`summarise()` regrouping output by 'chr' (override with `.groups` argument)
ggplot(bychr,aes(reorder(sample,dplyr::desc(sample)),total/1e6,fill=chr)) +
  theme_linedraw() + geom_bar(stat="identity") + coord_flip() +
  xlab("sample") + ylab("million reads") + ggsci::scale_fill_igv() +
  scale_x_discrete(limits = rev(levels(sample)))



# 前
#bychr <- mat %>% select(-(1:3)) %>%
#  gather("sample","count",-chr) %>%
#  group_by(chr,sample) %>% summarise(total=sum(count)) %>% ungroup

#ggplot(bychr,aes(reorder(sample,desc(sample)),total/1e6,fill=chr)) +
#  theme_linedraw() + geom_bar(stat="identity") + coord_flip() +
#  xlab("sample") + ylab("million reads") + ggsci::scale_fill_igv() +
#  scale_x_discrete(limits = rev(levels(sample)))


#bychr <- mat %>% select(-(1:3)) %>%
#  gather("sample","count",-chr) %>%
#  group_by(chr,sample) %>% summarise(total=sum(count)) %>% ungroup
#ggplot(bychr,aes(reorder(sample,dplyr::desc(sample)),total/1e6,fill=chr)) +
#  theme_linedraw() + geom_bar(stat="identity") + coord_flip() +
#  xlab("sample") + ylab("million reads") + ggsci::scale_fill_igv() +
#  scale_x_discrete(limits = rev(levels(sample)))

Biotype

bt <- mat %>% select(-c(1,2,4)) %>% group_by(biotype) %>%
  summarise_all(sum) %>% filter_at(-1,any_vars(. > 1000))
bt %>% tibble::column_to_rownames("biotype") %>%
  as.matrix %>% t %>% mosaicplot(las=2,shade=TRUE)

Correlations

drop rows with all 0 -> +1/2 -> geom.scale -> log -> Pearson’s

matf <- mat %>% filter(chr!="MT") %>% filter_at(-(1:4),any_vars(. > 0))
X <- matf %>% select(-(1:4)) %>% as.matrix
rownames(X) <- matf$ens_gene
lX <- log(gscale(X+0.5))
R <- cor(lX); diag(R) <- NA
pheatmap::pheatmap(R,color=viridis::viridis(256))

Dimension reduction

# set scale=TRUE if the patterns (not level) is the matter
p <- prcomp(t(lX[rank(-apply(lX,1,var)) <= ntop,]),scale=scalerows,center=TRUE)
screeplot(p,las=2,main="Importance")

print(summary(p)$imp[,seq(min(10,ncol(X)))])
                            PC1      PC2     PC3     PC4      PC5      PC6      PC7      PC8      PC9     PC10
Standard deviation     28.36722 9.792015 5.42517 5.21355 5.041439 4.451113 3.907467 3.733946 3.455748 3.357516
Proportion of Variance  0.72181 0.086010 0.02640 0.02438 0.022800 0.017770 0.013700 0.012510 0.010710 0.010110
Cumulative Proportion   0.72181 0.807820 0.83422 0.85860 0.881400 0.899170 0.912870 0.925370 0.936080 0.946200
label <- def %>% filter(sample %in% colnames(X))
df <- data.frame(p$x) %>% as_tibble(rownames="sample") %>%
  inner_join(label,.) %>% select(-file)
Joining, by = "sample"
print(df)
ggpoints(df,modifyList(aes(PC1,PC2),myaes))

ggpoints(df,modifyList(aes(PC2,PC3),myaes))


set.seed(seed)
um <- uwot::umap(p$x,n_nei,2)
df <- as_tibble(um) %>% rename(UMAP1=V1,UMAP2=V2) %>% bind_cols(df)
ggpoints(df,modifyList(aes(UMAP1,UMAP2),myaes))


print(df)
readr::write_csv(df,"CEL0386noumi_C2C12_Count_PCA_fin200915.csv")

DESeq2

Fit model

dds <- DESeq2::DESeqDataSetFromMatrix(X[,label$sample],label,model)
converting counts to integer mode
dds <- DESeq2::DESeq(dds)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
#=====#
# 20191213追加
dds <- DESeq2::estimateSizeFactors(dds)
norm <- DESeq2::counts(dds,normalized=TRUE) #DEGを取った後のクラスタリングに使う。

normalizedcount <- as.data.frame(norm) %>% tibble::rownames_to_column("ens_gene") %>% as_tibble
readr::write_csv(normalizedcount, "./CEL0386noumi_C2C12_H3mm18_normCount_fin200915.csv")

normalizedcount %>% inner_join(e2g, by = "ens_gene") %>% readr::write_csv("./CEL0386noumi_C2C12_normCount_genename_fin200915.csv")

####--- + size factors を書き出し ------------------####
as.data.frame(DESeq2::sizeFactors(dds))  %>% tibble::rownames_to_column("sample") %>% readr::write_csv("./CEL0386noumi_C2C12_H3mm18_sizefactors_fin200915_fin200915.csv")
as.data.frame(DESeq2::sizeFactors(dds))  %>% tibble::rownames_to_column("sample") 

#count_dds <- estimateSizeFactors(dds)
#counts(count_dds, normalized=TRUE)

vst => z score (200914add)


## 20200914

vsd <- DESeq2::vst(dds) #normalized countが入っている。(vstかrlog)
Xd <- SummarizedExperiment::assay(vsd) # 全て選択(200326) 20190920を元に (191024)
Xs <- Xd %>% t %>% scale %>% t

vst_score <- Xd %>% as.data.frame() %>% tibble::rownames_to_column("ens_gene") %>% as_tibble #200909 add
vst_type <- vst_score  %>% annotate %>% dplyr::select("ens_gene","ext_gene", "biotype","chr", all_of(label$sample))


zscore <- Xs %>% as.data.frame() %>% tibble::rownames_to_column("ens_gene") %>% as_tibble
zscore_type <- zscore  %>% annotate %>% dplyr::select("ens_gene","ext_gene", "biotype","chr", all_of(label$sample))

readr::write_csv(vst_score, "CEL0386noumi_C2C12_H3mm18__vst_all_fin200915.csv") #200909 add
readr::write_csv(vst_type, "CEL0386noumi_C2C12_H3mm18__vst_type_all_fin200915.csv") #200909 add
readr::write_csv(zscore, "CEL0386noumi_C2C12_H3mm18__zscore_all_fin200915.csv")
readr::write_csv(zscore_type, "CEL0386noumi_C2C12_H3mm18__zscore_type_all_fin200915.csv")


colnames(zscore_type)
 [1] "ens_gene"              "ext_gene"              "biotype"               "chr"                   "180122-eGFP-D72-lot1"  "180122-eGFP-D72-lot2"  "180130-eGFP-D72-lot1" 
 [8] "180130-eGFP-D72-lot2"  "180130-eGFP-D72-lot3"  "180121-eGFP-G-lot1"    "180121-eGFP-G-lot2"    "180403-eGFP-G-lot1"    "180403-eGFP-G-lot2"    "180403-eGFP-G-lot3"   
[15] "180122-mm18B-D72-lot1" "180122-mm18B-D72-lot2" "180130-mm18B-D72-lot1" "180130-mm18B-D72-lot2" "180130-mm18B-D72-lot3" "180121-mm18B-G-lot1"   "180121-mm18B-G-lot2"  
[22] "180403-mm18B-G-lot1"   "180403-mm18B-G-lot2"   "180403-mm18B-G-lot3"  
ncol(vst_type)
[1] 24
ncol(zscore_type)
[1] 24
nrow(vst_type)
[1] 23695
nrow(zscore_type)
[1] 23695
coef_dds <- coef(dds) %>% as.data.frame() %>% tibble::rownames_to_column("ens_gene") %>% as_tibble

readr::write_csv(coef_dds, "CEL0386noumi_C2C12_H3mm18__coefs_fin200915.csv")

Diagnostics plot

DESeq2::sizeFactors(dds) %>%
  {tibble(sample=names(.),sizeFactor=.)} %>%
  ggplot(aes(sample,sizeFactor)) + theme_minimal() +
  geom_bar(stat="identity") + coord_flip()

DESeq2::plotDispEsts(dds)

Extract results

#res <- mapply(function(x)
#  DESeq2::results(dds,x,lfcThreshold=lfcthreth,alpha=fdr)
#,contrast)

res <- mapply(function(x)
  DESeq2::results(dds,x,lfcThreshold=lfcthreth,alpha=fdr)
,contrast)


# 200914修正
re_all <- map(res,as_tibble,rownames="ens_gene") %>%
  tibble(aspect=factor(names(.),names(.)),data=.) %>%
  mutate(data=map(data,annotate)) %>%
  unnest(cols = "data")

re <- re_all %>% filter(padj<fdr) #191120修正 unnest() 


#re <- map(res,as_tibble,rownames="ens_gene") %>%
#  tibble(aspect=factor(names(.),names(.)),data=.) %>%
#  mutate(data=map(data,annotate)) %>%
#  unnest(cols = "data") %>% filter(padj<fdr)  #191120修正 unnest() 

fc <- re %>% select(1:7) %>% spread(aspect,log2FoldChange,fill=0)

imap(res,~{
  cat(paste0("-- ",.y," --"))
  DESeq2::summary(.x) #191120修正 DESeq2::summary.DESeqResults(.x)
}) %>% invisible
-- group_G_mm18B_vs_eGFP --
out of 23695 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 112, 0.47%
LFC < 0 (down)     : 220, 0.93%
outliers [1]       : 6, 0.025%
low counts [2]     : 11485, 48%
(mean count < 1)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results

-- group_D72_mm18B_vs_eGFP --
out of 23695 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 1036, 4.4%
LFC < 0 (down)     : 1022, 4.3%
outliers [1]       : 6, 0.025%
low counts [2]     : 11485, 48%
(mean count < 1)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results

-- group_eGFP_D72_vs_G --
out of 23695 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 2197, 9.3%
LFC < 0 (down)     : 2054, 8.7%
outliers [1]       : 6, 0.025%
low counts [2]     : 11025, 47%
(mean count < 1)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results

-- group_mm18B_D72_vs_G --
out of 23695 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up)       : 1807, 7.6%
LFC < 0 (down)     : 1447, 6.1%
outliers [1]       : 6, 0.025%
low counts [2]     : 10566, 45%
(mean count < 1)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results

Write-out tables

if(exists("fc"))   readr::write_csv(fc,"./2gun/Iwasaki_0386re_C2C12_H3mm18_noumi_l2fc__final200915.csv")
if(exists("re"))   readr::write_csv(re,"./2gun/Iwasaki_0386re_C2C12_H3mm18_noumi_results__final200915.csv")
if(exists("re_all"))   readr::write_csv(re_all,"./2gun/Iwasaki_0386re_C2C12_H3mm18_noumi_resultsall__final200915.csv")

DESeqのlog2FCの計算について (coef_ddsから計算する方法) (20200915検証)


# log2FC
re %>% filter(aspect=="group_G_mm18B_vs_eGFP") %>% filter(ens_gene %in% c("ENSMUSG00000088252","ENSMUSG00000024754","ENSMUSG00000024646","ENSMUSG00000032741","ENSMUSG00000031885"))


re %>% filter(aspect=="group_D72_mm18B_vs_eGFP") %>% filter(ens_gene %in% c("ENSMUSG00000088252","ENSMUSG00000024754","ENSMUSG00000024646","ENSMUSG00000032741","ENSMUSG00000031885"))

# coefから再現 (引き算をするだけで良い)
dddddd <- coef_dds %>% filter(ens_gene %in% c("ENSMUSG00000088252","ENSMUSG00000024754","ENSMUSG00000024646","ENSMUSG00000032741","ENSMUSG00000031885"))
dddddd %>% mutate(-group_eGFP_G_vs_mm18B_G, group_mm18B_D72_vs_mm18B_G-group_eGFP_D72_vs_mm18B_G)
NA

MAplot


## Growth ##

#maplot <- DESeq2::plotMA(res$group_G_mm18B_vs_eGFP, ylim=c(-6,6))
#print(maplot)

maplot <- DESeq2::plotMA(res$group_G_mm18B_vs_eGFP, ylim=c(-4,4),main="G mm18B vs eGFP")

print(maplot)
NULL
maplot <- DESeq2::plotMA(res$group_G_mm18B_vs_eGFP, ylim=c(-5,5),main="G mm18B vs eGFP")

print(maplot)
NULL
#maplot <- DESeq2::plotMA(res$group_G_mm18B_vs_eGFP, ylim=c(-2,2))
#print(maplot)


## D72 ##

#maplot <- DESeq2::plotMA(res$group_D72_mm18B_vs_eGFP, ylim=c(-6,6))
#print(maplot)

maplot <- DESeq2::plotMA(res$group_D72_mm18B_vs_eGFP, ylim=c(-4,4),main="D72 mm18B vs eGFP")

print(maplot)
NULL
maplot <- DESeq2::plotMA(res$group_D72_mm18B_vs_eGFP, ylim=c(-5,5),main="D72 mm18B vs eGFP")

print(maplot)
NULL
#maplot <- DESeq2::plotMA(res$group_D72_mm18B_vs_eGFP, ylim=c(-2,2))
#print(maplot)

こちらで横軸を計算してプロット 20200914add (20200915ver)


Set_cutoff <- 10.0

## 各時刻の平均を計算し、normalized count > 10 を超えるものを抽出する。

#----- 使用するデータのみ取り出す ---# 20200914
norm_plotlist_all <- normalizedcount %>% gather("sample", "normalized",-(ens_gene)) %>% inner_join(def, by = "sample") %>% mutate(time=factor(time, c("G","D72")))%>% mutate(type=factor(type,c("mm18B","eGFP"))) %>% mutate(group=factor(group,c("eGFP_G","mm18B_G","eGFP_D72", "mm18B_D72")))

#norm_plotlist_sel <- norm_plotlist_all %>% filter(sample %in% def_select$sample) %>% mutate(time=factor(time, c("G","D72")))%>% mutate(type=factor(type,c("eGFP","mm18B"))) %>% mutate(group=factor(group,c("eGFP_G","mm18B_G","eGFP_D72", "mm18B_D72")))

#notm_plotlist_cutoff <- norm_plotlist_all %>% annotate() %>% group_by(ens_gene, ext_gene, Day, intact_CTX) %>% summarise(groupMean=mean(normalized))  %>% ungroup() %>% dplyr::select(ens_gene, ext_gene) %>% unique()

## "eGFP","mm18B"関係なく平均を求める
notm_plotlist_beforecutoff <- norm_plotlist_all %>% annotate() %>% group_by(ens_gene, ext_gene, time) %>% summarise(groupMean=mean(normalized))
`summarise()` regrouping output by 'ens_gene', 'ext_gene' (override with `.groups` argument)
#notm_plotlist_beforecutoff <- norm_plotlist_sel %>% annotate() %>% group_by(ens_gene, ext_gene, time) %>% summarise(groupMean=mean(normalized))

notm_plotlist_cutoff <- notm_plotlist_beforecutoff %>% filter(groupMean > Set_cutoff) %>% ungroup() %>% dplyr::select(ens_gene, ext_gene) %>% unique()

nrow(notm_plotlist_beforecutoff %>% ungroup() %>% dplyr::select(ens_gene, ext_gene) %>% unique()) #この値をMAplotのx軸に使用
[1] 23695
nrow(notm_plotlist_cutoff) #解析対象を絞る (後の全体のクラスタリングに使用)
[1] 8641

norm_plotlist_all %>% readr::write_csv("Norm_deftable_all_final200915.csv")
#norm_plotlist_sel %>% readr::write_csv("Norm_deftable_select_final200915.csv") #これをMAplotに使用する
notm_plotlist_beforecutoff %>% readr::write_csv("Norm_groupMean_select_final200915.csv")
notm_plotlist_cutoff  %>% readr::write_csv("Norm_groupMean_select_cutoff10_final200915.csv")

nrow(norm_plotlist_all)
[1] 473900
#nrow(norm_plotlist_sel)
nrow(notm_plotlist_beforecutoff)
[1] 47390
nrow(notm_plotlist_cutoff)
[1] 8641

re_select_plot <- re_all %>% filter(aspect %in% c("group_G_mm18B_vs_eGFP","group_D72_mm18B_vs_eGFP")) %>% mutate(time=case_when(aspect=="group_G_mm18B_vs_eGFP"~"G",aspect=="group_D72_mm18B_vs_eGFP"~"D72",TRUE ~ "FALSE"))  %>% left_join(notm_plotlist_beforecutoff) %>% mutate(time=factor(time, c("G","D72")))
Joining, by = c("ens_gene", "ext_gene", "time")
re_select_plot %>% readr::write_csv("./MAplot/C2C12_mm18B_vs_eGFP_DEG_time_MAplotdata.csv")

####

Daymean <- re_select_plot %>% group_by(time) %>% summarise(DayMean=mean(groupMean))
`summarise()` ungrouping output (override with `.groups` argument)
Mean_color <- "#B8860B"

Daymean

Allgene_num <- re_select_plot %>% dplyr::select(ens_gene) %>% unique() %>% nrow()

f_DEG_in <- function(x) x %>% filter(padj<0.1)
f_DEG_out <- function(x) x %>% filter((!(padj<0.1))|is.na(padj))


f_inFC_degin <- function(x) x %>% f_DEG_in %>% filter(!(abs(log2FoldChange) > 5.0))
f_inFC_degout <- function(x) x %>% f_DEG_out %>% filter(!(abs(log2FoldChange) > 5.0))

f_overFC_up_degin <- function(x) x %>% f_DEG_in %>% filter(log2FoldChange > 5.0) %>% mutate(log2FoldChange=5.0) 
f_overFC_down_degin <- function(x) x %>% f_DEG_in %>% filter(log2FoldChange < -5.0) %>% mutate(log2FoldChange=-5.0)
f_overFC_up_degout <- function(x) x %>% f_DEG_out %>% filter(log2FoldChange > 5.0) %>% mutate(log2FoldChange=5.0)
f_overFC_down_degout <- function(x) x %>% f_DEG_out %>% filter(log2FoldChange < -5.0) %>% mutate(log2FoldChange=-5.0)


### 全て
re_select_plot %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
### DEG
re_select_plot %>% f_DEG_in %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
re_select_plot %>% f_inFC_degin %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
re_select_plot %>% f_overFC_up_degin %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
re_select_plot %>% f_overFC_down_degin %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
### DEG 以外
re_select_plot %>% f_DEG_out %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
re_select_plot %>% f_inFC_degout %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
re_select_plot %>% f_overFC_up_degout %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
re_select_plot %>% f_overFC_down_degout %>% group_by(aspect) %>% summarise(n())
`summarise()` ungrouping output (override with `.groups` argument)
ddddddddd <- re_select_plot  %>% f_DEG_in %>% mutate(FC_updown = case_when(log2FoldChange>0~"Up", log2FoldChange<0~"Down")) %>% mutate(FC_updown=factor(FC_updown,c("Up","Down"))) %>% arrange(time,FC_updown)
eeeeeeeee <- ddddddddd  %>% group_by(aspect,time,FC_updown) %>% summarise(count=n())
`summarise()` regrouping output by 'aspect', 'time' (override with `.groups` argument)
gggglabel <- paste("C2C12 mm18B_vs_eGFP:", Allgene_num, "genes,",
                   "G:",eeeeeeeee$FC_updown[1],eeeeeeeee$count[1],",",eeeeeeeee$FC_updown[2],eeeeeeeee$count[2],
                   ",","D72:",eeeeeeeee$FC_updown[3],eeeeeeeee$count[3],",",eeeeeeeee$FC_updown[4],eeeeeeeee$count[4],sep=" ")
print(gggglabel)
[1] "C2C12 mm18B_vs_eGFP: 23695 genes, G: Up 112 , Down 220 , D72: Up 1036 , Down 1022"
######

ggmaplot <- re_select_plot  %>%  ggplot(aes(groupMean,log2FoldChange))+geom_point(size=0.1, alpha = 0.5,data=f_DEG_out,color="#bdbdbd") + geom_abline(intercept=0,slope=0,colour="black",size=0.2) +geom_point(aes(groupMean,log2FoldChange),size=0.1,color="#ff0000", data=f_DEG_in) + scale_x_log10() + theme_bw() + theme(legend.position = "top") + ggtitle(gggglabel) + ylim(-5.0, 5.0) + facet_wrap(~time,ncol=1) + theme(axis.title = element_text(size=15),axis.text = element_text(size=10),axis.text.x = element_text(hjust = 0.5,vjust=1.0), legend.position = "right", strip.text=element_text(size=15),strip.background = element_blank(),title = element_text(size=5))

#+ scale_color_manual(values = c("#ff0000","#ff0000","#000000")) 

ggsave(file="./MAplot/C2C12_mm18B_vs_eGFP_DEG_time_MAplot.pdf", plot = ggmaplot, width = 6, height = 8, dpi = 120)
plot(ggmaplot)


ggmaplot <- re_select_plot  %>%  ggplot(aes(groupMean,log2FoldChange))+geom_point(size=0.1, alpha = 0.5,data=f_DEG_out,color="#bdbdbd") + geom_abline(intercept=0,slope=0,colour="black",size=0.2)  + geom_vline(data = Daymean, aes(xintercept=DayMean),colour=Mean_color,size=0.2,linetype="dashed") +geom_point(aes(groupMean,log2FoldChange),size=0.1,color="#ff0000", data=f_DEG_in) + scale_x_log10() + theme_bw() + theme(legend.position = "top") + ggtitle(gggglabel) + ylim(-5.0, 5.0) + facet_wrap(~time,ncol=1) + theme(axis.title = element_text(size=15),axis.text = element_text(size=10),axis.text.x = element_text(hjust = 0.5,vjust=1.0), legend.position = "right", strip.text=element_text(size=15),strip.background = element_blank(),title = element_text(size=5))

#+ scale_color_manual(values = c("#ff0000","#ff0000","#000000")) 

ggsave(file="./MAplot/C2C12_mm18B_vs_eGFP_DEG_time_MAplot_Mean.pdf", plot = ggmaplot, width = 6, height = 8, dpi = 120)
plot(ggmaplot)

######
## FC over5も出力


ggmaplot <-  re_select_plot  %>%  ggplot(aes(groupMean,log2FoldChange))+geom_point(size=0.1, alpha = 0.5,data=f_inFC_degout,color="#bdbdbd") +geom_point(size=0.2, alpha = 0.5,shape=2,data=f_overFC_up_degout,color="#bdbdbd")+geom_point(size=0.2, alpha = 0.5,shape=6,data=f_overFC_down_degout,color="#bdbdbd") + geom_abline(intercept=0,slope=0,colour="black",size=0.2)  +geom_point(aes(groupMean,log2FoldChange),size=0.1,color="#ff0000", data=f_inFC_degin) +geom_point(size=0.3, shape=2,data=f_overFC_up_degin,color="#ff0000") +geom_point(size=0.3, shape=6,data=f_overFC_down_degin,color="#ff0000")  + scale_x_log10() + theme_bw() + theme(legend.position = "top") + ggtitle(gggglabel) + ylim(-5.0, 5.0) + facet_wrap(~time,ncol=1) + theme(axis.title = element_text(size=15),axis.text = element_text(size=10),axis.text.x = element_text(hjust = 0.5,vjust=1.0), legend.position = "right", strip.text=element_text(size=15),strip.background = element_blank(),title = element_text(size=5))

ggsave(file="./MAplot/C2C12_mm18B_vs_eGFP_DEG_time_MAplot_over5.pdf", plot = ggmaplot, width = 6, height = 8, dpi = 120)
plot(ggmaplot)


ggmaplot <-  re_select_plot  %>%  ggplot(aes(groupMean,log2FoldChange))+geom_point(size=0.1, alpha = 0.5,data=f_inFC_degout,color="#bdbdbd") +geom_point(size=0.2, alpha = 0.5,shape=2,data=f_overFC_up_degout,color="#bdbdbd")+geom_point(size=0.2, alpha = 0.5,shape=6,data=f_overFC_down_degout,color="#bdbdbd") + geom_abline(intercept=0,slope=0,colour="black",size=0.2)  + geom_vline(data = Daymean, aes(xintercept=DayMean),colour=Mean_color,size=0.2,linetype="dashed") +geom_point(aes(groupMean,log2FoldChange),size=0.1,color="#ff0000", data=f_inFC_degin) +geom_point(size=0.3, shape=2,data=f_overFC_up_degin,color="#ff0000") +geom_point(size=0.3, shape=6,data=f_overFC_down_degin,color="#ff0000")  + scale_x_log10() + theme_bw() + theme(legend.position = "top") + ggtitle(gggglabel) + ylim(-5.0, 5.0) + facet_wrap(~time,ncol=1) + theme(axis.title = element_text(size=15),axis.text = element_text(size=10),axis.text.x = element_text(hjust = 0.5,vjust=1.0), legend.position = "right", strip.text=element_text(size=15),strip.background = element_blank(),title = element_text(size=5))

ggsave(file="./MAplot/C2C12_mm18B_vs_eGFP_DEG_time_MAplot_Mean_over5.pdf", plot = ggmaplot, width = 6, height = 8, dpi = 120)
plot(ggmaplot)

GO解析

20191204追加 mouse, CTX, 2群間 (Up, Down) の結果GOを参考に。 (191120ver)

2群間 (Up, Down) の結果をGO



table_degcluster <- re %>% filter(aspect=="group_D72_mm18B_vs_eGFP") %>% arrange(ens_gene) %>% dplyr::select(ens_gene,ext_gene,log2FoldChange)

#file_degcluster <- "/home/guestA/o70578a/akuwakado/kuwakado/scCELSeq2/Iwasaki_0386_C2C12_H3mm18/Final_Last_Rserver_200523/Iwasaki_0386re_C2C12_H3mm18_noumi_results__final200523.csv"
#table_degcluster <- readr::read_csv(file_degcluster) %>% filter(aspect=="group_D72_mm18B_vs_eGFP") %>% arrange(ens_gene) %>% dplyr::select(ens_gene,ext_gene,log2FoldChange)

# plus
table_degcluster %>% filter(log2FoldChange>0) %>% summarise(plus = dplyr::n())

# minus
table_degcluster %>% filter(log2FoldChange<0) %>% summarise(minus = dplyr::n())

##### FDR setting ######
gofdr <- 0.1

cluster_num <- 2

20191106修正を参考に Up Down用

(20200915, defaltのGOのplotの調子が悪い)

library(clusterProfiler)
library(org.Mm.eg.db)


#-------------#

filename_list <- "./clusterProfile/Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_log2FoldChange_BPfdr0p1_generatio_"
filename_csv <- "./clusterProfile/Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_log2FoldChange_BPfdr0p1_generatio_UpDown"

#-------------#

cluster_list <- as.list(NA) #初期化

for (i in 1:2) {
  pre_list <- as.list(NA)  #初期化
   
  if (i == 1) { 
    pre_list <- table_degcluster %>%  filter(log2FoldChange>0) %>% dplyr::select(ens_gene) %>% as.list()
    #pre_list <- table_degcluster %>% filter(log2FoldChange=="Up") %>% dplyr::select(ens_gene) %>% as.list()
    names(pre_list) <- paste("ENSEMBL",as.character("up"),sep="_")
  } 
  else { 
    pre_list <- table_degcluster %>%  filter(log2FoldChange<0) %>% dplyr::select(ens_gene) %>% as.list()
    names(pre_list) <- paste("ENSEMBL",as.character("down"),sep="_")
  }
   
  if (i == 1) { 
     cluster_list <- pre_list
  } 
  else cluster_list <- c(cluster_list, pre_list) 
}



for (i in 1:2) {
  print(paste(i, cluster_list[[i]] %>% tibble::enframe(name = NULL) %>% nrow(), sep=", "))
  #print(paste(i, cluster_list[[i]] %>% as_tibble() %>% nrow(), sep=", ")) #Calling `as_tibble()` on a vector is discouraged, because the behavior is likely to change in the future. Use `tibble::enframe(name = NULL)` instead.
   
  pre_ego_BP <- enrichGO(gene = cluster_list[[i]],
                 OrgDb = "org.Mm.eg.db",
                 keyType = 'ENSEMBL',
                 ont = "BP",
                 pAdjustMethod = "BH",
                 pvalueCutoff  = gofdr, qvalueCutoff  = 1.0)
   
   ## pvalue < qvalue < p.adjust ##
   # qvalueCutoff  = 0.3  qvalueCutoff  = 0.2 , qvalueCutoff  = 1.0

  if (i == 1) { 
     table_ego_BP <- data.frame(pre_ego_BP) %>% mutate(cluster="Up")  # リスト型からデータフレームへ変換
     #---- plot ---#
     #BPplot <- dotplot(pre_ego_BP, showCategory=30, orderBy = "Count") #clusterProfile の機能で図を描く(191106修正) wrong orderBy parameter; set to default `orderBy = "x"`
     #print(BPplot)
     #ggsave(BPplot,file=paste(filename_list,"Up",".png",sep=""), width = 8, height = 12, dpi = 120)
  } 
  else {
     table_ego_BP <- table_ego_BP %>% bind_rows(data.frame(pre_ego_BP) %>% mutate(cluster="Down"))
     #---- plot ---#
     #BPplot <- dotplot(pre_ego_BP, showCategory=30, orderBy = "Count") #clusterProfile の機能で図を描く(191106修正) wrong orderBy parameter; set to default `orderBy = "x"`
     #print(BPplot)
     #ggsave(BPplot,file=paste(filename_list,"Down",".png",sep=""), width = 8, height = 12, dpi = 120)
  }
}
[1] "1, 1036"
[1] "2, 1022"
#------#
# データはtable_ego_BPに。
print(table_ego_BP %>% group_by(cluster) %>% summarise())
`summarise()` ungrouping output (override with `.groups` argument)
#------------------------------------------------------#
# テーブルを保存

table_ego_BP1 <- table_ego_BP %>% mutate(cluster=factor(cluster,c("Up","Down"))) %>% arrange(cluster,desc(Count)) #191106

readr::write_csv(table_ego_BP1,paste(filename_csv,".csv",sep=""))

# 先のテーブルのgeneIDをgene nameに置換する。(20191025)

tablego <- table_ego_BP1 %>% mutate(gene_name=geneID) %>% dplyr::select(-(qvalue))

for (i in 1:nrow(table_degcluster)) {
  tablego <- tablego %>% mutate(gene_name=gsub(gene_name, pattern=table_degcluster$ens_gene[i], replacement=table_degcluster$ext_gene[i], ignore.case = TRUE))
}

print(tablego)

readr::write_csv(tablego,paste(filename_csv,"_genename.csv",sep=""))

#------------------------------------------------------#

#GOのtermの数
print(tablego %>% group_by(cluster) %>% summarise(count_GO=n()))
`summarise()` ungrouping output (override with `.groups` argument)
## 変更 ##
table_ego_BP_2gunfdr0p1_cluster <- tablego # 自由に変更する

#--- メモ ----#
#tableggg <- table_ego_clustercluster
#colm <- tableggg$geneID
#for (i in 1:88) {
#  colm <- sub(rrres_cluster3$ens_gene[i], rrres_cluster3$ext_gene[i], colm)
#}
#print(colm)
# Benjamini correction を p-adjust として使用する
# figのタイトルを修正 (20191213)

file_BP_plot <- "./clusterProfile/BPfdr0p1__Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_log2FoldChange_fin200915.pdf"
file_BP_plot_muscle <- "./clusterProfile/BPfdr0p1__Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_2gunfdr0p1_log2FoldChange_muscleonly_fin200915.pdf"


#--------------------#

BP_matome <- tablego

rowlength <- BP_matome %>% group_by(Description) %>% summarise() %>% nrow()
`summarise()` ungrouping output (override with `.groups` argument)
BP_plot <- BP_matome %>% filter(p.adjust<fdr) %>% ggplot(aes(x=cluster, y=reorder(Description,Count), size=Count, fill=p.adjust)) + geom_point(shape = 21) + theme(strip.text = element_text(size = 10)) + theme_minimal() + theme(strip.text = element_text(size = 12),axis.text.x = element_text(angle = 45, hjust = 1)) + scale_fill_gradient(low = "red" , high = "blue")+ xlab("C2C12 (fdr 0.1)") + ylab("GO Description (BP)") + labs(fill=paste("p.adjust (BH) < ",as.character(fdr),sep=""))
print(BP_plot)
ggsave(plot=BP_plot,file=file_BP_plot, width = 10, height = (5+rowlength/6), dpi = 120,limitsize = FALSE)


#---muscle関連のみ
BP_matome_muscle <- BP_matome %>% filter(grepl("muscle", Description)|grepl("myo", Description))
rowlength <- BP_matome_muscle %>% group_by(Description) %>% summarise() %>% nrow()
`summarise()` ungrouping output (override with `.groups` argument)
BP_plot_muscle <- BP_matome_muscle %>% filter(p.adjust<fdr) %>% ggplot(aes(x=cluster, y=reorder(Description,Count), size=Count, fill=p.adjust)) + geom_point(shape = 21) + theme(strip.text = element_text(size = 10)) + theme_minimal() + theme(strip.text = element_text(size = 12),axis.text.x = element_text(angle = 45, hjust = 1)) + scale_fill_gradient(low = "red" , high = "blue") + xlab("C2C12 (fdr 0.1) (muscle)") + ylab("GO Description (BP)") + labs(fill=paste("p.adjust (BH) < ",as.character(fdr),sep=""))
print(BP_plot_muscle)
ggsave(BP_plot_muscle,file=file_BP_plot_muscle, width = 8, height = (5+rowlength/6), dpi = 120,limitsize = FALSE)

NA
NA

# x=pvalue, y=p.adjust
plottt <- table_ego_BP %>% ggplot(aes(x=pvalue, y=p.adjust, size=Count)) + geom_point()+geom_abline(intercept=0,slope=1.0,linetype="dashed",colour="blue") + xlim(0,NA) + ylim(0,NA) + ggtitle(label=paste("p.adjust (BH) < ",as.character(fdr),sep=""))
print(plottt)


# x=pvalue, y=qvalue
plottt <- table_ego_BP %>% ggplot(aes(x=pvalue, y=qvalue, size=Count)) + geom_point()+geom_abline(intercept=0,slope=1.0,linetype="dashed",colour="blue") + xlim(0,NA) + ylim(0,NA) + ggtitle(label=paste("p.adjust (BH) < ",as.character(fdr),sep=""))
print(plottt)


# x=p.adjust, y=qvalue
plottt <- table_ego_BP %>% ggplot(aes(x=p.adjust, y=qvalue, size=Count)) + geom_point()+geom_abline(intercept=0,slope=1.0,linetype="dashed",colour="blue") + xlim(0,NA) + ylim(0,NA) + ggtitle(label=paste("p.adjust (BH) < ",as.character(fdr),sep=""))
print(plottt)



## pvalue < qvalue < p.adjust ##
# pvalue < p.adjust
# pvalue < qvalue
# qvalue < p.adjust

#---------------------#

#[BBRB-seq_0438_QC_tmpl_v6_noumi_190515-H3mm18KO_CTX_S2-Day0_S3_fdr0p2ver_and_LRT_191024  (umi補正なし,fdr0.2) (TPM 190722ver) (190924を元に) (190627-1024)]を参考にした。

#pvalueCutoff   
#pvalue cutoff on enrichment tests to report

#pAdjustMethod  
#one of "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none"

#qvalueCutoff   
#qvalue cutoff on enrichment tests to report as significant. Tests must pass i) pvalueCutoff on unadjusted pvalues, ii) pvalueCutoff on adjusted pvalues and iii) qvalueCutoff on qvalues to be reported.

# 設定(pvalueCutoff  = 0.1, qvalueCutoff  = 0.2)だと、p値<0.1, p.adjust値<0.1, q値<0.2 になっている。

plot Top GO (20200915 add)


tablego_top <- tablego %>% group_by(cluster) %>% arrange(desc(Count), p.adjust, pvalue) %>% mutate(rank=row_number()) %>% filter(rank<=10)
print(tablego_top)

filename <- paste(dirname(filename_csv),"/Top10__",basename(filename_csv),"_genename.csv",sep="")
print(filename)
[1] "./clusterProfile/Top10__Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_log2FoldChange_BPfdr0p1_generatio_UpDown_genename.csv"
readr::write_csv(tablego_top,filename)

# C2 Top10
#file_c2 <- "/home/akuwakado/makeplot_18project/Inputfile/Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_log2FoldChange_BPfdr0p1_generatio_UpDown_genename.csv"
#datac2 <- readr::read_csv(file_c2) %>% group_by(cluster) %>% arrange(desc(Count), p.adjust, pvalue) %>% mutate(rank=row_number()) %>% filter(rank<=10)
#print(datac2)
#filename <- paste("./Outputfile/","Top10__",basename(file_c2),sep="")
#print(filename)
#datac2 %>% readr::write_csv(filename)

一度に描画


plot_tablego_top <- tablego_top %>% ungroup()  %>% mutate(cluster=factor(cluster,c("Up","Down"))) %>% group_by(cluster) %>% dplyr::mutate(GeneRatio1=GeneRatio) %>% tidyr::separate(col=GeneRatio1,sep="/",into=c("count","BP_genesize")) %>% mutate(BP_genesize=as.integer(BP_genesize),Gene_ratio=Count/BP_genesize) %>% dplyr::select(-count)

plot_tablego_top %>% summarise(max=max(Gene_ratio),min=min(Gene_ratio))
`summarise()` ungrouping output (override with `.groups` argument)
plot_tablego_top %>% summarise(max=max(Count),min=min(Count))
`summarise()` ungrouping output (override with `.groups` argument)
plot_tablego_top_2 <- plot_tablego_top %>% mutate(new_Description = paste("(",cluster,") ",Description,sep=""))

#xmax=0.175
#xmin=0.085
#all_break <- c(3,6,9,12,15)


xmax=0.085
xmin=0.050
#all_break <- c(55,60,65,70,75,80,85)
all_break <- c(50,55,60,65,70,75) #+ scale_size_area(breaks=all_break)

sort_plot_tablego_top_2 <- plot_tablego_top_2 %>% arrange(desc(rank))

gggU <- plot_tablego_top_2 %>% arrange(desc(rank)) %>% mutate(new_Description =factor(new_Description,sort_plot_tablego_top_2$new_Description)) %>% ggplot(aes(x=Gene_ratio, y=new_Description, fill=p.adjust)) + geom_point(aes(size=Count),shape = 21) + theme_bw() + theme(legend.position = "right",legend.box="horizontal",strip.text = element_text(size = 12),legend.title = element_text(size = 14),axis.title = element_text(size = 14),legend.text = element_text(size = 12),axis.text = element_text(size = 12),axis.text.x = element_text(vjust = 1),strip.background = element_blank()) + scale_fill_gradient(low = "red" , high = "blue",limits = c(0, 0.1)) + xlim(xmin,xmax) + facet_wrap(~cluster,scales = "free_y",ncol=1)

gggU0 <- plot_tablego_top_2 %>% arrange(desc(rank)) %>% mutate(new_Description =factor(new_Description,sort_plot_tablego_top_2$new_Description))  %>% ggplot(aes(x=Gene_ratio, y=new_Description, fill=p.adjust)) + geom_point(aes(size=Count),shape = 21) + theme_bw() + theme(legend.position = "right",legend.box="horizontal",strip.text = element_blank(),legend.title = element_blank(),axis.title = element_blank(),legend.text = element_blank(),axis.text = element_blank(),axis.text.x = element_blank(),strip.background = element_blank()) + scale_fill_gradient(low = "red" , high = "blue",limits = c(0, 0.1)) + xlim(xmin,xmax) + facet_wrap(~cluster,scales = "free_y",ncol=1)

print(gggU)

print(gggU0)


filename <- paste(dirname(filename_csv),"/Top10__",basename(filename_csv),"_plot.pdf",sep="")
print(filename)
[1] "./clusterProfile/Top10__Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_log2FoldChange_BPfdr0p1_generatio_UpDown_plot.pdf"
ggsave(gggU,file=filename, width = 8, height = 7, dpi = 120,limitsize = FALSE)

filename <- paste(dirname(filename_csv),"/Top10__",basename(filename_csv),"_plot_none.pdf",sep="")
print(filename)
[1] "./clusterProfile/Top10__Iwasaki_0386re_C2C12_H3mm18_2gunfdr0p1_log2FoldChange_BPfdr0p1_generatio_UpDown_plot_none.pdf"
ggsave(gggU0,file=filename, width = 4, height = 7, dpi = 120,limitsize = FALSE)


#ggsave(gggU,file=paste("./Outputfile/","C2C12_H3mm18_CEL0386re__clusterAll_Top10_BPfdr0p1_plot.pdf",sep=""), width = 8, height = 7, dpi = 120,limitsize = FALSE)
#ggsave(gggU0,file=paste("./Outputfile/","C2C12_H3mm18_CEL0386re__clusterAll_Top10_BPfdr0p1_plot_none.pdf",sep=""), width = 4, height = 7, dpi = 120,limitsize = FALSE)

Top GO term heatmap

(GO 20200915ver)


GOdata_top10 <- tablego_top

raa <- strsplit(GOdata_top10$geneID , "/")

for (i in 1:nrow(GOdata_top10)) {
  rbbb <- data.frame(Description=rep(GOdata_top10$Description[i],length(raa[[i]])), cluster=rep(GOdata_top10$cluster[i],length(raa[[i]])), ens_gene=raa[[i]])

  if (i == 1) {
    Top10GO <- rbbb
  } 
  else {
     Top10GO <- Top10GO %>% bind_rows(rbbb)
  }
}

Top10GO_t <- Top10GO %>% as_tibble() %>% mutate(Description=as.character(Description),ens_gene=as.character(ens_gene),cluster=as.character(cluster))

Top10GO_s <- Top10GO_t %>% group_by(ens_gene,cluster) %>% summarise(Des=paste(Description, collapse = ", ")) %>% ungroup()
`summarise()` regrouping output by 'ens_gene' (override with `.groups` argument)
readr::write_csv(Top10GO_s, "./clusterProfile/heatmap/CEL0386noumi_C2C12_H3mm18__DEG_GOtop10_genelist__20200915.csv")

Top10GO_s_down <- Top10GO_s %>% filter(cluster=="Down")
Top10GO_s_up <- Top10GO_s %>% filter(cluster=="Up")  

zscore_type_Top10GO_deg <- zscore_type %>% filter(ens_gene %in% Top10GO_s$ens_gene)

zscore_type_Top10GO_up <- zscore_type %>% filter(ens_gene %in% Top10GO_s_up$ens_gene)
zscore_type_Top10GO_down <- zscore_type %>% filter(ens_gene %in% Top10GO_s_down$ens_gene)

zscore_type_housekeep <- zscore_type %>% filter(ext_gene %in% c("Rpl27","Actb","Gapdh"))
re %>% filter(ext_gene %in% c("Rpl27","Actb","Gapdh"))
NA

z score heatmap (new)


breaksList = seq(-3.0, 3.0, 0.1)
heatmapcols <- colorRampPalette(rev(brewer.pal(n=7,name="RdYlBu")))(length(breaksList))

def_select <- def %>% dplyr::filter(group %in% c("mm18B_G", "eGFP_G","mm18B_D72", "eGFP_D72")) %>% mutate(group=factor(group,c("eGFP_G","mm18B_G","eGFP_D72", "mm18B_D72"))) %>% arrange(group,sample)
#================================================#


#anno_row <- data.frame(Chr = zscore_BRBDEG$chr, cluster = zscore_BRBDEG$cluster)
#rownames(anno_row) <- zscore_BRBDEG$ext_gene

#anno_col <- data.frame(Seq = def_list_select$seq, Dox = def_list_select$type)
#rownames(anno_col) <- def_list_select$sample
#================================================#


zscore_mat_down <-  zscore_type_Top10GO_down %>% dplyr::select(all_of(def_select$sample)) %>% as.matrix()
rownames(zscore_mat_down) <- zscore_type_Top10GO_down$ext_gene
heat_title_down <- paste("Top10GO down: ",nrow(zscore_type_Top10GO_down)," Total: ",nrow(zscore_type),sep="")

zscore_mat_up <-  zscore_type_Top10GO_up %>% dplyr::select(all_of(def_select$sample)) %>% as.matrix()
rownames(zscore_mat_up) <- zscore_type_Top10GO_up$ext_gene
heat_title_up <- paste("Top10GO up: ",nrow(zscore_type_Top10GO_up)," Total: ",nrow(zscore_type),sep="")

zscore_mat_keep <-  zscore_type_housekeep %>% dplyr::select(all_of(def_select$sample)) %>% as.matrix()
rownames(zscore_mat_keep) <- zscore_type_housekeep$ext_gene
heat_title_keep <- paste("Housekeeping: ",nrow(zscore_type_housekeep)," Total: ",nrow(zscore_type),sep="")


#================================================#
z_heat1 <- pheatmap::pheatmap(zscore_mat_down,
                                  
     main = heat_title_down,
                                  
     scale = "none",
     
     #cluster_rows = FALSE, #peak (clusterで)  (領域名)
     #cluster_cols = FALSE, #samplrf
     #cluster_rows = FALSE, #peak (clusterで)  (領域名)
     cluster_rows = TRUE, #peak (clusterで)  (領域名)
     cluster_cols = FALSE, #samplrf

     #show_rownames = TRUE, #peak名 (領域名)
     show_rownames = TRUE, #peak名 (領域名)
     show_colnames = TRUE, #sample_position名 (モチーフ名)
     
     #annotation_names_col = TRUE,
     #show_rownames = TRUE, #peak名
     #show_colnames = TRUE, #sample_position名
     #annotation_names_col =TRUE,
     #gaps_row=table_gap$nonoo,
     #gaps_col=c(3,6,8,11),
     
     #na_col ="white",

     gaps_row=c(80),
     gaps_col= seq(5, 20, 5),
     #gaps_col= seq(2, 8*2, 2),
     #gaps_col= c(2,4,6,8,10,12,14), # c(3, 6, 9, 12), #gaps_col= seq(2, 6*2, 2),
     #gaps_col=c(200,400,600,800,1000,1200,1400,1600,1800,2000,2200,2400), gaps_col= seq(200, 12*200, 200),
     #cellheight = nrow(mymatrix2_1)*(0.25),
     #cellwidth = 20,
     #cellheight = 400/nrow(mymatrix1),
     #cellheight = 0.005,   #cellheight = 1.5,
     #cellheight = 0.010,   #cellheight = 1.5,
     cellheight = 4.0,   #cellheight = 1.5,
     cellwidth = 40,      #cellwidth = 3,
     #cellheight = 0.7,   #cellheight = 1.5,
     #cellwidth = 8,      #cellwidth = 3,
     #cellheight = 6,   #cellheight = 1.5,

     #cellheight = 6,   #cellheight = 1.5,
     #cellwidth = 7,      #cellwidth = 3,
     #cellheight = 0.7,   #cellheight = 1.5,
     #cellwidth = 15,      #cellwidth = 3,
     #border_color="gray",  #border_color="#000000",
     border_color=NA,
     #fontsize_row = 6,
     #annotation_row = mixed_name,
     #annotation_row = anno_row,
     #annotation_col = anno_col,
     
#     cutree_rows = 6,
     #cutree_rows = 10,
     
     #display_numbers = TRUE,
     #number_format = "%1.2e",
     #number_color = "black",
     #annotation_col = annotdf_sample
     fontsize_col = 5,
     fontsize_row = 3.7,
     #fontsize_row = 0.6,
     legend=TRUE,
     #legend_breaks = leg_break,
     #legend_labels = as.character(leg_break),
     breaks = breaksList,
     color = heatmapcols
     #annotation_colors = mycolors
     #treeheight_row = 10
)


ggsave(plot=z_heat1,file="./clusterProfile/heatmap/heatmap_down.pdf", width = 15, height = 15, dpi = 360, limitsize = FALSE)

#================================================#
z_heat1 <- pheatmap::pheatmap(zscore_mat_up,
                                  
     main = heat_title_up,
                                 
     scale = "none",
     
     #cluster_rows = FALSE, #peak (clusterで)  (領域名)
     #cluster_cols = FALSE, #samplrf
     #cluster_rows = FALSE, #peak (clusterで)  (領域名)
     cluster_rows = TRUE, #peak (clusterで)  (領域名)
     cluster_cols = FALSE, #samplrf

     #show_rownames = TRUE, #peak名 (領域名)
     show_rownames = TRUE, #peak名 (領域名)
     show_colnames = TRUE, #sample_position名 (モチーフ名)
     
     #annotation_names_col = TRUE,
     #show_rownames = TRUE, #peak名
     #show_colnames = TRUE, #sample_position名
     #annotation_names_col =TRUE,
     #gaps_row=table_gap$nonoo,
     #gaps_col=c(3,6,8,11),
     
     #na_col ="white",

     gaps_row=c(80),
     gaps_col= seq(5, 20, 5),
     #gaps_col= seq(2, 8*2, 2),
     #gaps_col= c(2,4,6,8,10,12,14), # c(3, 6, 9, 12), #gaps_col= seq(2, 6*2, 2),
     #gaps_col=c(200,400,600,800,1000,1200,1400,1600,1800,2000,2200,2400), gaps_col= seq(200, 12*200, 200),
     #cellheight = nrow(mymatrix2_1)*(0.25),
     #cellwidth = 20,
     #cellheight = 400/nrow(mymatrix1),
     #cellheight = 0.005,   #cellheight = 1.5,
     #cellheight = 0.010,   #cellheight = 1.5,
     cellheight = 4.0,   #cellheight = 1.5,
     cellwidth = 40,      #cellwidth = 3,
     #cellheight = 0.7,   #cellheight = 1.5,
     #cellwidth = 8,      #cellwidth = 3,
     #cellheight = 6,   #cellheight = 1.5,

     #cellheight = 6,   #cellheight = 1.5,
     #cellwidth = 7,      #cellwidth = 3,
     #cellheight = 0.7,   #cellheight = 1.5,
     #cellwidth = 15,      #cellwidth = 3,
     #border_color="gray",  #border_color="#000000",
     border_color=NA,
     #fontsize_row = 6,
     #annotation_row = mixed_name,
     #annotation_row = anno_row,
     #annotation_col = anno_col,
     
#     cutree_rows = 6,
     #cutree_rows = 10,
     
     #display_numbers = TRUE,
     #number_format = "%1.2e",
     #number_color = "black",
     #annotation_col = annotdf_sample
     fontsize_col = 5,
     fontsize_row = 3.7,
     #fontsize_row = 0.6,
     legend=TRUE,
     #legend_breaks = leg_break,
     #legend_labels = as.character(leg_break),
     breaks = breaksList,
     color = heatmapcols
     #annotation_colors = mycolors
     #treeheight_row = 10
)


#ggsave(plot=z_heat1,file="./H3K27me3_ChIL_heatmap.png", width = 8, height = 15, dpi = 360, limitsize = FALSE)
ggsave(plot=z_heat1,file="./clusterProfile/heatmap/heatmap_up.pdf", width = 15, height = 20, dpi = 360, limitsize = FALSE)

#================================================#
z_heat1 <- pheatmap::pheatmap(zscore_mat_keep,
                                  
     main = heat_title_keep,
                                  
     scale = "none",
     
     
     #cluster_rows = FALSE, #peak (clusterで)  (領域名)
     #cluster_cols = FALSE, #samplrf
     #cluster_rows = FALSE, #peak (clusterで)  (領域名)
     cluster_rows = TRUE, #peak (clusterで)  (領域名)
     cluster_cols = FALSE, #samplrf

     #show_rownames = TRUE, #peak名 (領域名)
     show_rownames = TRUE, #peak名 (領域名)
     show_colnames = TRUE, #sample_position名 (モチーフ名)
     
     #annotation_names_col = TRUE,
     #show_rownames = TRUE, #peak名
     #show_colnames = TRUE, #sample_position名
     #annotation_names_col =TRUE,
     #gaps_row=table_gap$nonoo,
     #gaps_col=c(3,6,8,11),
     
     #na_col ="white",

     gaps_row=c(80),
     gaps_col= seq(5, 20, 5),
     #gaps_col= seq(2, 8*2, 2),
     #gaps_col= c(2,4,6,8,10,12,14), # c(3, 6, 9, 12), #gaps_col= seq(2, 6*2, 2),
     #gaps_col=c(200,400,600,800,1000,1200,1400,1600,1800,2000,2200,2400), gaps_col= seq(200, 12*200, 200),
     #cellheight = nrow(mymatrix2_1)*(0.25),
     #cellwidth = 20,
     #cellheight = 400/nrow(mymatrix1),
     #cellheight = 0.005,   #cellheight = 1.5,
     #cellheight = 0.010,   #cellheight = 1.5,
     cellheight = 4.0,   #cellheight = 1.5,
     cellwidth = 40,      #cellwidth = 3,
     #cellheight = 0.7,   #cellheight = 1.5,
     #cellwidth = 8,      #cellwidth = 3,
     #cellheight = 6,   #cellheight = 1.5,

     #cellheight = 6,   #cellheight = 1.5,
     #cellwidth = 7,      #cellwidth = 3,
     #cellheight = 0.7,   #cellheight = 1.5,
     #cellwidth = 15,      #cellwidth = 3,
     #border_color="gray",  #border_color="#000000",
     border_color=NA,
     #fontsize_row = 6,
     #annotation_row = mixed_name,
     #annotation_row = anno_row,
     #annotation_col = anno_col,
     
#     cutree_rows = 6,
     #cutree_rows = 10,
     
     #display_numbers = TRUE,
     #number_format = "%1.2e",
     #number_color = "black",
     #annotation_col = annotdf_sample
     fontsize_col = 5,
     fontsize_row = 3.7,
     #fontsize_row = 0.6,
     legend=TRUE,
     #legend_breaks = leg_break,
     #legend_labels = as.character(leg_break),
     breaks = breaksList,
     color = heatmapcols
     #annotation_colors = mycolors
     #treeheight_row = 10
)


#ggsave(plot=z_heat1,file="./H3K27me3_ChIL_heatmap.png", width = 8, height = 15, dpi = 360, limitsize = FALSE)
ggsave(plot=z_heat1,file="./clusterProfile/heatmap/heatmap_housekeeping.pdf", width = 15, height = 15, dpi = 360, limitsize = FALSE)

normalized count plot

# 2019 12月作成

norm_plotlist_all_name <- norm_plotlist_all %>% inner_join(e2g, by = "ens_gene") 
readr::write_csv(norm_plotlist_all_name,"Norm_deftable_all_final200915__genename.csv") #191206 追加

nrow(norm_plotlist_all)
[1] 473900
nrow(norm_plotlist_all_name)
[1] 473900

norm_plotlist_all “Norm_deftable_all_final200915.csv” を使う


plotgene_list <- c("Col3a1","Acta1","Myog","Myod1","Tnnt1","Tnnt2","Tnnt3","Csrp3","Myh3","Ckm","Rpl27","Actb","Gapdh","Slc38a2","Inhba","Myh9","Rpl13","Nsdhl")
length(plotgene_list)
[1] 18
#"Myh3","Ckm","Acta1","Tnnt2","Actb","Csrp3"

re %>% filter(aspect=="group_D72_mm18B_vs_eGFP") %>% filter(ext_gene %in% plotgene_list) %>% arrange(log2FoldChange)

#======== Change every data ここで順番を変更 ========#

#-------#

nbl <- norm_plotlist_all_name %>% filter(ext_gene %in% plotgene_list)

#====================================================#

f_gene_norm <- function(x) x %>% group_by(group, type, time, ext_gene) %>% summarise(avg=mean(normalized),se=sd(normalized)/sqrt(length(normalized))) %>% ungroup()

#----#
nbl %>% group_by(group, type, time) %>% summarise()
`summarise()` regrouping output by 'group', 'type' (override with `.groups` argument)
#----#

#face="italic"
#, axis.text.x = element_text(angle = 45, hjust = 1) #X軸のラベルを傾ける場合
#, axis.text.x = element_text(hjust = 0.5) #X軸のラベルを水平にする場合

### point ###
gggggpp <-  ggplot(nbl,aes(time,normalized,group=type,colour=type))+geom_point(size=2)+facet_wrap(~ext_gene,scale="free_y",nrow=3)+geom_line(size=1.0, aes(x=time,y=avg,colour=type),data=f_gene_norm)+theme_bw() + ylim(0,NA) + theme(axis.text=element_text(hjust = 1, size=16), axis.text.x = element_text(hjust = 0.5), axis.title=element_text(size=16),axis.title.x = element_blank(), legend.title=element_text(size=16), legend.text = element_text(size=16), strip.background = element_blank(), strip.text.x = element_text(size=20,face="italic"), legend.position = "top",  plot.title=element_text(size=16))+ggsci::scale_color_npg()  + ylab("normalized count")

file_path <- "./normCount/normCount_plot_final200915_plot1.pdf"
print(file_path)
[1] "./normCount/normCount_plot_final200915_plot1.pdf"
ggsave(file=file_path, plot = gggggpp, dpi = 100, width = 12, height = 10)

print(gggggpp)



gggggpp <-  ggplot(nbl,aes(time,normalized,group=type,colour=type))+geom_point(size=2)+facet_wrap(~ext_gene,scale="free_y",nrow=3)+geom_smooth(se=FALSE)+theme_bw() + ylim(0,NA) + theme(axis.text=element_text(hjust = 1, size=16), axis.text.x = element_text(hjust = 0.5), axis.title=element_text(size=16),axis.title.x = element_blank(), legend.title=element_text(size=16), legend.text = element_text(size=16), strip.background = element_blank(), strip.text.x = element_text(size=20,face="italic"), legend.position = "top",  plot.title=element_text(size=16))+ggsci::scale_color_npg()  + ylab("normalized count")

file_path <- "./normCount/normCount_plot_final200915_plot1_smooth.pdf"
print(file_path)
[1] "./normCount/normCount_plot_final200915_plot1_smooth.pdf"
ggsave(file=file_path, plot = gggggpp, dpi = 100, width = 12, height = 9)

TPM

TPMで作図 (191203修正)

# カウント0も表示するように変更 (20190722)

tpm <- umi %>% group_by(sample) %>% mutate(sample_total=sum(count),TPM=count/sum(count)*1e6) %>% ungroup
tpm_zero <- tpm %>% select(sample,ens_gene,TPM) %>% spread(sample,TPM,fill=0) %>% gather(sample, TPM, -ens_gene) #カウント0のサンプルは0を入れる 20190722追加して修正

tpm_def <- def %>% select(-count) %>% dplyr::inner_join(tpm_zero, by = "sample") #tpmをtpm_zeroに修正、20190722修正

matome <- tpm_def %>% inner_join(e2g, by = "ens_gene")

readr::write_csv(matome,"Iwasaki_0386re_C2C12_H3mm18_umi_TPM__final20915.csv") #191203 追加

#-- 確認 --#
umi %>% group_by(sample) %>% summarise(sum(count)) # 確認
`summarise()` ungrouping output (override with `.groups` argument)
tpm_zero %>% group_by(sample) %>% summarise(sum(TPM)) # 確認
`summarise()` ungrouping output (override with `.groups` argument)
head(matome)

#-- 覚書 --#
#tpm %>% filter(ens_gene=="ENSMUSG00000043090") #17個
#tpm_zero %>% filter(ens_gene=="ENSMUSG00000043090") #32個

# -- 旧ver ---
#tpm <- umi %>% group_by(sample) %>% mutate(sample_total=sum(count),TPM=count/sum(count)*1e6) %>% ungroup
#umi %>% group_by(sample) %>% summarise(sum(count))
#tpm %>% group_by(sample) %>% summarise(sum(TPM))
#tpm_def <- def %>% select(-count) %>% dplyr::inner_join(tpm, by = "sample")
LS0tCnRpdGxlOiAiW0xhc3QgMjAwOTE1LCAxOHByb2plY3QsIEMyQzEyXSBDRUxzZXFfUUNfSXdhc2FraV8wMzg2X0MyQzEyX0gzbW0xOF9ub3VtaV8yMDE5MDYxM18wNzIyX2ZpbjE5MTIwM18yMDA1MjN2ZXJfbGFzdDIwMDkxNSAoMjAwOTE1LCAyMDA1MjMsMTkxMjAzLTE5MTIwNCwxOTA3MjIsMTkwNjEzLCAxOTA1MTQtNjEwKSBbbm91bWkgKHVzZSAuY291bnRzLnR4dCldIHZlci5uYiIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB5ZXMKICBwZGZfZG9jdW1lbnQ6IAogICAga2VlcF90ZXg6IHllcwogICAgbGF0ZXhfZW5naW5lOiBsdWFsYXRleAotLS0KCiMjIyBTZXR1cAoKYGBge3IgbGlicmFyaWVzLG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShwdXJycikKc291cmNlKCIvaG9tZS9ndWVzdEEvbjcwMjc1Yi93b3JrL3JzY3JpcHRzL2dlb21Ob3JtLlIiKQoKIyBIZWxwZXIgZnVuY3Rpb24KI2dncG9pbnRzIDwtIGZ1bmN0aW9uKHgsLi4uKSAKIyAgZ2dwbG90KHgsLi4uKSArIGdlb21fcG9pbnQoc2l6ZT0zLHN0cm9rZT0xKSArCiMgIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChzaXplPTQpICsgdGhlbWVfbWluaW1hbCgpICsgbXljb2xvcgoKIyMg44Op44OZ44Or44GC44KKCmdncG9pbnRzIDwtIGZ1bmN0aW9uKHgsLi4uKSAKICBnZ3Bsb3QoeCwuLi4pICsgZ2VvbV9wb2ludChzdHJva2U9MSkgKwogIGdncmVwZWw6Omdlb21fdGV4dF9yZXBlbChzaXplPTQpICsgdGhlbWVfbWluaW1hbCgpICsgbXljb2xvcgoKIyMg44Op44OZ44Or44Gq44GXCiNnZ3BvaW50cyA8LSBmdW5jdGlvbih4LC4uLikgCiMgIGdncGxvdCh4LC4uLikgKyBnZW9tX3BvaW50KHN0cm9rZT0xKSArIHRoZW1lX21pbmltYWwoKSArIG15Y29sb3IKCgpwcmludChTeXMuRGF0ZSgpKQpwcmludChzZXNzaW9uSW5mbygpLGxvY2FsZT1GQUxTRSkKCnNlbGVjdCA8LSBkcGx5cjo6c2VsZWN0CnJlbmFtZSA8LSBkcGx5cjo6cmVuYW1lICMxOTEyMDMKY291bnQgPC0gZHBseXI6OmNvdW50ICMxOTEyMDMKCgoKYGBgCgojIyMgUGFyYW1ldGVycwoKKm1vZGlmeSBoZXJlKgoKYGBge3IgcGFyYW1zfQojIEZpbGVzCgpkZWZ0YWJsZSA8LSAiL2hvbWUvZ3Vlc3RBL283MDU3OGEvYWt1d2FrYWRvL2t1d2FrYWRvL3NjQ0VMU2VxMi9Jd2FzYWtpXzAzODZfQzJDMTJfSDNtbTE4L0ZpbmFsX0xhc3RfUnNlcnZlcl8yMDA1MjMvaXdhc2FraV8wMzg2X25vdW1pX2RlZl9maW4xOTEyMDNfXzIwMDUyM3Zlci50eHQiICPmnIDntYLniYggMTIxMjAzCgoKI2RlZnRhYmxlIDwtICIvaG9tZS9ndWVzdEEvbzcwNTc4YS9ha3V3YWthZG8va3V3YWthZG8vc2NDRUxTZXEyL0l3YXNha2lfMDM4Nl9DMkMxMl9IM21tMTgvaXdhc2FraV8wMzg2X3VtaV9kZWZfZmluMTkxMjAzdmVyLnR4dCIgI+acgOe1gueJiCAxMjEyMDMKI2RlZnRhYmxlIDwtICIvaG9tZS9ndWVzdEEvbzcwNTc4YS9ha3V3YWthZG8va3V3YWthZG8vc2NDRUxTZXEyL0l3YXNha2lfMDM4Nl9DMkMxMl9IM21tMTgvaXdhc2FraV8wMzg2X3VtaV9kZWYudHh0IgoKI2RlZnRhYmxlIDwtICJkZWZ0YWJsZV9CUkJfdW1pX25ldy50eHQiCgojIyBEYXRhIHNlbGVjdGlvbiAoZmlsdGVyIHJvd3Mgb2YgZGVmdGFibGUpCiN1c2UgPC0gcXVvKCFncmVwbCgiXjE4Iixncm91cCkgJiAoZ3JvdXAgIT0gIk5jLW1pbnVzVHJ5ZCIpKQojdXNlIDwtIHF1byhUUlVFKSAjIHVzZSBhbGwKdXNlIDwtICBxdW8oZ3JvdXAgJWluJSBjKCJlR0ZQX0ciLCJtbTE4Ql9HIiwiZUdGUF9ENzIiLCAibW0xOEJfRDcyIikpCiN1c2UgPC0gcXVvKHR5cGUgPT0gIkMyQzEyIikKI3VzZSA8LSBxdW8odHlwZSAhPSAiQzJDMTIiKQojdXNlIDwtIHF1byhUUlVFKQoKI3VzZSA8LSBxdW8odHlwZSA9PSAiV2hvbGVfY2VsbCIpCiN1c2UgPC0gcXVvKHR5cGUgPT0gIk51Y2xldXMiKQoKIyBTcGVjaWVzIHNwZWNpZmljIHBhcmFtZXRlcnMKc3BlY2llcyA8LSAiTXVzIG11c2N1bHVzIgpiaW9tYXJ0YW5uIDwtICJtbXVzY3VsdXNfZ2VuZV9lbnNlbWJsIgptYXhjaHJvbSA8LSAxOSAjIDE5OiBtb3VzZSwgMjI6IGh1bWFuCgojIEdyYXBoaWNzCiMgYWVzdGhldGljIG1hcHBpbmcgb2YgbGFiZWxzCiNteWFlcyA8LSBhZXMoY29sb3VyPWVuenltZSxzaGFwZT1sZWcsbGFiZWw9cmVwKSAKCiNteWFlcyA8LSBhZXMoY29sb3VyPWdyb3d0aCxzaGFwZT10eXBlLHNpemU9Y291bnQpICPjg6njg5njg6vjgarjgZcKI215YWVzIDwtIGFlcyhjb2xvdXI9Z3Jvd3RoLHNoYXBlPXR5cGUsbGFiZWw9cmVwbGljYXRlLHNpemU9Y291bnQpICPjg6njg5njg6vjgYLjgooKI215YWVzIDwtIGFlcyhjb2xvdXI9ZW56eW1lLHNoYXBlPWxlZyxsYWJlbD1yZXBsaWNhdGUpICPjg6njg5njg6vjgYLjgooKI215YWVzIDwtIGFlcyhjb2xvdXI9ZW56eW1lLHNoYXBlPWxlZyxsYWJlbD1mYWN0b3IocmVwKSkKCiNteWFlcyA8LSBhZXMoY29sb3VyPXR5cGUsc2hhcGU9dHJ5cHNpbixsYWJlbD1mYWN0b3IobG90KSkgCiNteWFlcyA8LSBhZXMoY29sb3VyPXRyeXBzaW4sbGFiZWw9ZmFjdG9yKGxvdCkpIApteWFlcyA8LSBhZXMoY29sb3VyPXRpbWUsc2hhcGU9dHlwZSxsYWJlbD1mYWN0b3IobG90KSkgCgojIGNvbG9yIHBhbGV0dGUgb2YgcG9pbnRzOiBTZWUgdmlnbmV0dGUoImdnc2NpIikKI215Y29sb3IgPC0gZ2dzY2k6OnNjYWxlX2NvbG9yX2FhYXMoKQpteWNvbG9yIDwtIGdnc2NpOjpzY2FsZV9jb2xvcl9kMygiY2F0ZWdvcnkyMCIpICMgY29sb3IgcGFsZXR0ZSBvZiBwb2ludHMKCiMgUENBL1VNQVAKc2NhbGVyb3dzIDwtIFRSVUUgIyBnZW5lLXdpc2Ugc2NhbGluZyAocGF0dGVybiBpcyB0aGUgbWF0dGVyPykKbnRvcCA8LSA1MDAgIyBudW1iZXIgb2YgdG9wLW4gZ2VuZXMgd2l0aCBoaWdoIHZhcmlhbmNlCnNlZWQgPC0gMTIzICMgc2V0IGFub3RoZXIgbnVtYmVyIGlmIFVNQVAgbG9va3Mgbm90IGdvb2QKbl9uZWkgPC0gMiAgIzYgIyBudW1iZXIgb2YgbmVpZ2hib3JpbmcgZGF0YSBwb2ludHMgaW4gVU1BUAoKI2hhc2hpZ3VzaGkKc2NhbGVyb3dzIDwtIEZBTFNFICMgZ2VuZS13aXNlIHNjYWxpbmcgKHBhdHRlcm4gaXMgdGhlIG1hdHRlcj8pCiNzZWVkIDwtIDEyMyAjIHNldCBhbm90aGVyIG51bWJlciBpZiB0U05FIGxvb2tzIG5vdCBnb29kCiNwZXJwcmV4aXR5IDwtIDMgIyBleHBlY3RlZCBjbHVzdGVyIHNpemUgaW4gdFNORQoKIyBERVNlcTIKI21vZGVsIDwtIH50eXBlK3RyeXBzaW4KCiNtb2RlbCA8LSB+dHJ5cHNpbgptb2RlbCA8LSB+Z3JvdXAKCgpmZHIgPC0gMC4xICMgYWNjZXB0YWJsZSBmYWxzZSBkaXNjb3ZlcnkgcmF0ZQpsZmN0aHJldGggPC0gbG9nMigxKSAjIHRocmVzaG9sZCBpbiBhYnMobG9nMkZDKQojIGNvbnRyb2xzIHNob3VsZCBiZSBwbGFjZWQgaW4gdGhlIHJpZ2h0CmNvbnRyYXN0IDwtIGxpc3QoIAogIAogICN0aW1lX0Q3Ml92c19HID0gYygidGltZSIsICJENzIiLCAiRyIpCiAgCgoKICAjZ3JvdXBfR19IM2YzYl92c19XVCA9IGMoImdyb3VwIiwgIkgzZjNiX0ciLCAiV1RfRyIpLAogICNncm91cF9HX21tMThCX3ZzX1dUID0gYygiZ3JvdXAiLCAibW0xOEJfRyIsICJXVF9HIiksCiAgI2dyb3VwX0dfZUdGUF92c19XVCA9IGMoImdyb3VwIiwgImVHRlBfRyIsICJXVF9HIiksCiAgI2dyb3VwX0dfSDNmM2JfdnNfZUdGUCA9IGMoImdyb3VwIiwgIkgzZjNiX0ciLCAiZUdGUF9HIiksCiAgZ3JvdXBfR19tbTE4Ql92c19lR0ZQID0gYygiZ3JvdXAiLCAibW0xOEJfRyIsICJlR0ZQX0ciKSwKICAjZ3JvdXBfR19tbTE4Ql92c19IM2YzYiA9IGMoImdyb3VwIiwgIm1tMThCX0ciLCAiSDNmM2JfRyIpLAogIAogICNncm91cF9ENzJfSDNmM2JfdnNfV1QgPSBjKCJncm91cCIsICJIM2YzYl9ENzIiLCAiV1RfRDcyIiksCiAgI2dyb3VwX0Q3Ml9tbTE4Ql92c19XVCA9IGMoImdyb3VwIiwgIm1tMThCX0Q3MiIsICJXVF9ENzIiKSwKICAjZ3JvdXBfRDcyX2VHRlBfdnNfV1QgPSBjKCJncm91cCIsICJlR0ZQX0Q3MiIsICJXVF9ENzIiKSwKICAjZ3JvdXBfRDcyX0gzZjNiX3ZzX2VHRlAgPSBjKCJncm91cCIsICJIM2YzYl9ENzIiLCAiZUdGUF9ENzIiKSwKICBncm91cF9ENzJfbW0xOEJfdnNfZUdGUCA9IGMoImdyb3VwIiwgIm1tMThCX0Q3MiIsICJlR0ZQX0Q3MiIpLAogICNncm91cF9ENzJfbW0xOEJfdnNfSDNmM2IgPSBjKCJncm91cCIsICJtbTE4Ql9ENzIiLCAiSDNmM2JfRDcyIikKICAKICAgICNncm91cF9XVF9ENzJfdnNfRyA9IGMoImdyb3VwIiwgIldUX0Q3MiIsICJXVF9HIiksCiAgZ3JvdXBfZUdGUF9ENzJfdnNfRyA9IGMoImdyb3VwIiwgImVHRlBfRDcyIiwgImVHRlBfRyIpLCAgCiAgI2dyb3VwX0gzZjNiX0Q3Ml92c19HID0gYygiZ3JvdXAiLCAiSDNmM2JfRDcyIiwgIkgzZjNiX0ciKSwKICBncm91cF9tbTE4Ql9ENzJfdnNfRyA9IGMoImdyb3VwIiwgIm1tMThCX0Q3MiIsICJtbTE4Ql9HIikKICAKCiAgCiAgI3R5cGUgPSBjKCJ0eXBlIiwgIk51Y2xldXMiLCAiV2hvbGVfY2VsbCIpLAogICN0cnlwc2luID0gYygidHJ5cHNpbiIsICJwbHVzIiwgInVudHJlYXRlZCIpCiAgCiAgI0ludGVyY2VwdCA9IGxpc3QoIkludGVyY2VwdCIpLCAjIHJlZmVyZW5jZSBsZXZlbAogICNsZWdfTHZzUiA9IGMoImxlZyIsICJMIiwgIlIiKSwKICAjZW56X0t2c0MgPSBjKCJlbnp5bWUiLCJLIiwiQyIpCiAgI2xlZ0wuZW56SyA9IGxpc3QoImxlZ0wuZW56eW1lSyIpICMgaW50ZXJhY3Rpb24KICAKICAjdHlwZV9Eb3hwbHVzX3ZzX21pbnVzID0gYygidHlwZSIsICJEb3hwbHVzIiwgIkRveG1pbnVzIikKKQpgYGAKCgoKIyMjIFJldHJpZXZlIEJpb21hcnQKCmBgYHtyIGJpb21hcnQsIGNhY2hlPVRSVUV9CmlmKCFleGlzdHMoImUyZyIpKXsKICBlbnNlbWJsIDwtIGJpb21hUnQ6OnVzZU1hcnQoIkVOU0VNQkxfTUFSVF9FTlNFTUJMIixob3N0PSJhc2lhLmVuc2VtYmwub3JnIikKICAjZW5zZW1ibCA8LSBiaW9tYVJ0Ojp1c2VNYXJ0KCJFTlNFTUJMX01BUlRfRU5TRU1CTCIsaG9zdD0idXN3ZXN0LmVuc2VtYmwub3JnIikKICAjZW5zZW1ibCA8LSBiaW9tYVJ0Ojp1c2VNYXJ0KCJFTlNFTUJMX01BUlRfRU5TRU1CTCIsaG9zdD0idXNlYXN0LmVuc2VtYmwub3JnIikKICBtYXJ0IDwtIGJpb21hUnQ6OnVzZURhdGFzZXQoYmlvbWFydGFubixtYXJ0PWVuc2VtYmwpCiAgZTJnIDwtIGJpb21hUnQ6OmdldEJNKGF0dHJpYnV0ZXM9YygiZW5zZW1ibF9nZW5lX2lkIiwiZXh0ZXJuYWxfZ2VuZV9uYW1lIiwKICAgICJnZW5lX2Jpb3R5cGUiLCJjaHJvbW9zb21lX25hbWUiKSwgbWFydD1tYXJ0KSAlPiUgYXNfdGliYmxlICU+JQogIHJlbmFtZSgKICAgIGVuc19nZW5lID0gZW5zZW1ibF9nZW5lX2lkLAogICAgZXh0X2dlbmUgPSBleHRlcm5hbF9nZW5lX25hbWUsCiAgICBiaW90eXBlID0gZ2VuZV9iaW90eXBlLAogICAgY2hyID0gY2hyb21vc29tZV9uYW1lCiAgKQp9CmFubm90YXRlIDwtIHBhcnRpYWwocmlnaHRfam9pbixlMmcsYnk9ImVuc19nZW5lIikKCiMtLS0tLSMKbnJvdyhlMmcpCnJlYWRyOjp3cml0ZV9jc3YoZTJnLCJlbnNlbWJsZV9saXN0X2FzaWFfX2ZpbjIwMDkxNS5jc3YiKQojcmVhZHI6OndyaXRlX2NzdihlMmcsImVuc2VtYmxlX2xpc3RfdXN3ZXN0X2ZpbjIwMDUyMy5jc3YuY3N2IikKIyNyZWFkcjo6d3JpdGVfY3N2KGUyZywiZW5zZW1ibGVfbGlzdF91c2Vhc3QuY3N2IikKCiNlMmcgPC0gcmVhZHI6OnJlYWRfY3N2KCIvaG9tZS9ndWVzdEEvbzcwNTc4YS9ha3V3YWthZG8va3V3YWthZG8vc2NDRUxTZXEyL0l3YXNha2lfMDM4Nl9DMkMxMl9IM21tMTgvRmluYWxfTGFzdF9Sc2VydmVyXzIwMDUyMy9lbnNlbWJsZV9saXN0X3Vzd2VzdF9maW4yMDA1MjMuY3N2LmNzdiIpCiNhbm5vdGF0ZSA8LSBwYXJ0aWFsKHJpZ2h0X2pvaW4sZTJnLGJ5PSJlbnNfZ2VuZSIpCiNucm93KGUyZykKCmBgYAoKIyMjIExvYWQgY291bnRzCgpgYGB7ciBsb2FkVU1JfQoKZGVmIDwtIHJlYWRyOjpyZWFkX3RzdihkZWZ0YWJsZSkgJT4lIGZpbHRlcighIXVzZSkgJT4lIGFycmFuZ2UoZ3JvdXAsc2FtcGxlKSAjMjAyMDA5MTUgY2hhbmdlCnByaW50KGRlZikKcmVhZHI6OndyaXRlX2NzdihkZWYsImRlZnRhYmxlX3VzZWRfQ0VMMDM4Nm5vdW1pX0MyQzEyX2ZpbjIwMDkxNS5jc3YiKQoKIyMjIy0tLSBOZXcgLS0tIyMjIyAobm8gVU1JID8pCiMgU2V0IHJlZmVyZW5jZSBsZXZlbHMgYWNjb3JkaW5nIHRvIHRoZSBjb250cmFzdApmb3IoeCBpbiBrZWVwKGNvbnRyYXN0LGlzLmNoYXJhY3RlcikpCiAgZGVmW1t4WzFdXV0gPC0gcmVsZXZlbChmYWN0b3IoZGVmW1t4WzFdXV0pLHhbM10pCgp1bWkgPC0gZGVmJGZpbGUgJT4lIHVuaXF1ZSAlPiUgdGliYmxlKGZpbGU9LikgJT4lIAogIGRwbHlyOjptdXRhdGUoZGF0YT1tYXAoZmlsZSxyZWFkcjo6cmVhZF90c3YscHJvZ3Jlc3M9RkFMU0UpKSAlPiUKICB1bm5lc3QoKSAlPiUgZHBseXI6OnJlbmFtZShiYXJjb2RlPWNlbGwpICU+JQogIGRwbHlyOjppbm5lcl9qb2luKHNlbGVjdChkZWYsZmlsZSxiYXJjb2RlLHNhbXBsZSksLixjKCJmaWxlIiwiYmFyY29kZSIpKSAlPiUKICBzZWxlY3QoLWZpbGUsLWJhcmNvZGUpICU+JSBkcGx5cjo6cmVuYW1lKGVuc19nZW5lPWdlbmUpCgpwcmludCh1bWkpCgojIyBzYW1wbGUsIGJhcmNvZGUsIGZpbGUg44KS5b+Y44KM44Ga44Gr77yBCgptYXQgPC0gdW1pICU+JSBhbm5vdGF0ZSAlPiUKICBkcGx5cjo6bXV0YXRlKGNocj1mYWN0b3IoY2hyLGMoMTptYXhjaHJvbSwiWCIsIlkiLCJNVCIpKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShjaHIpKSAlPiUgc3ByZWFkKHNhbXBsZSxjb3VudCxmaWxsPTApCiMjIHRvIGNoZWNrIHJlYWQgdmlhcywgdGhpcyBhZGQgcmVhZCBudW1iZXIgYXMgIm4iIGNvbHVtbiAoMjAxOS80LzE5KQpkZWYgPC0gdW1pICU+JSBjb3VudChzYW1wbGUsd3Q9Y291bnQpICU+JSBkcGx5cjo6aW5uZXJfam9pbihkZWYsLikgJT4lIGRwbHlyOjpyZW5hbWUoY291bnQ9bikKIyMjIy0tLS0tLS0tLS0tIyMjIyAKCgojZGVmIDwtIHJlYWRyOjpyZWFkX3RzdihkZWZ0YWJsZSkgJT4lIGZpbHRlcighIXVzZSkKCiMjIyMtLS0gTmV3IC0tLSMjIyMgKG5vIFVNSSA/KQojIFNldCByZWZlcmVuY2UgbGV2ZWxzIGFjY29yZGluZyB0byB0aGUgY29udHJhc3QKI2Zvcih4IGluIGtlZXAoY29udHJhc3QsaXMuY2hhcmFjdGVyKSkKIyAgZGVmW1t4WzFdXV0gPC0gcmVsZXZlbChmYWN0b3IoZGVmW1t4WzFdXV0pLHhbM10pCgojdW1pIDwtIGRlZiRmaWxlICU+JSB1bmlxdWUgJT4lIHRpYmJsZShmaWxlPS4pICU+JSAKIyAgZHBseXI6Om11dGF0ZShkYXRhPW1hcChmaWxlLHJlYWRyOjpyZWFkX3Rzdixwcm9ncmVzcz1GQUxTRSkpICU+JQojICB1bm5lc3QoKSAlPiUgZHBseXI6OnJlbmFtZShiYXJjb2RlPWNlbGwpICU+JQojICBpbm5lcl9qb2luKHNlbGVjdChkZWYsZmlsZSxiYXJjb2RlLHNhbXBsZSksLixjKCJmaWxlIiwiYmFyY29kZSIpKSAlPiUKIyAgc2VsZWN0KC1maWxlLC1iYXJjb2RlKSAlPiUgZHBseXI6OnJlbmFtZShlbnNfZ2VuZT1nZW5lKQoKIyMgc2FtcGxlLCBiYXJjb2RlLCBmaWxlIOOCkuW/mOOCjOOBmuOBq++8gQoKI21hdCA8LSB1bWkgJT4lIGFubm90YXRlICU+JQojICBkcGx5cjo6bXV0YXRlKGNocj1mYWN0b3IoY2hyLGMoMTptYXhjaHJvbSwiWCIsIlkiLCJNVCIpKSkgJT4lCiMgIGZpbHRlcighaXMubmEoY2hyKSkgJT4lIHNwcmVhZChzYW1wbGUsY291bnQsZmlsbD0wKQojIyB0byBjaGVjayByZWFkIHZpYXMsIHRoaXMgYWRkIHJlYWQgbnVtYmVyIGFzICJuIiBjb2x1bW4gKDIwMTkvNC8xOSkKI2RlZiA8LSB1bWkgJT4lIGNvdW50KHNhbXBsZSx3dD1jb3VudCkgJT4lIGlubmVyX2pvaW4oZGVmLC4pICU+JSBkcGx5cjo6cmVuYW1lKGNvdW50PW4pCiMjIyMtLS0tLS0tLS0tLSMjIyMgCgojIE9sZAojIFNldCByZWZlcmVuY2UgbGV2ZWxzIGFjY29yZGluZyB0byB0aGUgY29udHJhc3QKI2Zvcih4IGluIGtlZXAoY29udHJhc3QsaXMuY2hhcmFjdGVyKSkKIyAgZGVmW1t4WzFdXV0gPC0gcmVsZXZlbChmYWN0b3IoZGVmW1t4WzFdXV0pLHhbM10pCiN1bWkgPC0gZGVmJGZpbGUgJT4lIHVuaXF1ZSAlPiUgdGliYmxlKGZpbGU9LikgJT4lIAojICBtdXRhdGUoZGF0YT1tYXAoZmlsZSxyZWFkcjo6cmVhZF90c3YscHJvZ3Jlc3M9RkFMU0UpKSAlPiUKIyAgdW5uZXN0KCkgJT4lIHJlbmFtZShiYXJjb2RlPWNlbGwpICU+JQojICBpbm5lcl9qb2luKHNlbGVjdChkZWYsZmlsZSxiYXJjb2RlLHNhbXBsZSksLixjKCJmaWxlIiwiYmFyY29kZSIpKSAlPiUKIyAgc2VsZWN0KC1maWxlLC1iYXJjb2RlKSAlPiUgcmVuYW1lKGVuc19nZW5lPWdlbmUpCiNtYXQgPC0gdW1pICU+JSBhbm5vdGF0ZSAlPiUKIyAgbXV0YXRlKGNocj1mYWN0b3IoY2hyLGMoMTptYXhjaHJvbSwiWCIsIlkiLCJNVCIpKSkgJT4lCiMgIGZpbHRlcighaXMubmEoY2hyKSkgJT4lIHNwcmVhZChzYW1wbGUsY291bnQsZmlsbD0wKQoKCgpwcmludCh1bWkpCnByaW50KGRlZikKYGBgCgojIyMgUmVhZHMgYnJlYWtkb3duCgojIyMjIFRvdGFsIHJlYWRzCgpgYGB7ciB0b3RhbFJlYWRzLCBmaWcud2lkdGg9NyxmaWcuaGVpZ2h0PTV9CgpieWNociA8LSBtYXQgJT4lIHNlbGVjdCgtKDE6MykpICU+JQogIGdhdGhlcigic2FtcGxlIiwiY291bnQiLC1jaHIpICU+JQogIGdyb3VwX2J5KGNocixzYW1wbGUpICU+JSBzdW1tYXJpc2UodG90YWw9c3VtKGNvdW50KSkgJT4lIHVuZ3JvdXAKCmdncGxvdChieWNocixhZXMocmVvcmRlcihzYW1wbGUsZHBseXI6OmRlc2Moc2FtcGxlKSksdG90YWwvMWU2LGZpbGw9Y2hyKSkgKwogIHRoZW1lX2xpbmVkcmF3KCkgKyBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgY29vcmRfZmxpcCgpICsKICB4bGFiKCJzYW1wbGUiKSArIHlsYWIoIm1pbGxpb24gcmVhZHMiKSArIGdnc2NpOjpzY2FsZV9maWxsX2lndigpICsKICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IHJldihsZXZlbHMoc2FtcGxlKSkpCgoKIyDliY0KI2J5Y2hyIDwtIG1hdCAlPiUgc2VsZWN0KC0oMTozKSkgJT4lCiMgIGdhdGhlcigic2FtcGxlIiwiY291bnQiLC1jaHIpICU+JQojICBncm91cF9ieShjaHIsc2FtcGxlKSAlPiUgc3VtbWFyaXNlKHRvdGFsPXN1bShjb3VudCkpICU+JSB1bmdyb3VwCgojZ2dwbG90KGJ5Y2hyLGFlcyhyZW9yZGVyKHNhbXBsZSxkZXNjKHNhbXBsZSkpLHRvdGFsLzFlNixmaWxsPWNocikpICsKIyAgdGhlbWVfbGluZWRyYXcoKSArIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKyBjb29yZF9mbGlwKCkgKwojICB4bGFiKCJzYW1wbGUiKSArIHlsYWIoIm1pbGxpb24gcmVhZHMiKSArIGdnc2NpOjpzY2FsZV9maWxsX2lndigpICsKIyAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSByZXYobGV2ZWxzKHNhbXBsZSkpKQoKCiNieWNociA8LSBtYXQgJT4lIHNlbGVjdCgtKDE6MykpICU+JQojICBnYXRoZXIoInNhbXBsZSIsImNvdW50IiwtY2hyKSAlPiUKIyAgZ3JvdXBfYnkoY2hyLHNhbXBsZSkgJT4lIHN1bW1hcmlzZSh0b3RhbD1zdW0oY291bnQpKSAlPiUgdW5ncm91cAojZ2dwbG90KGJ5Y2hyLGFlcyhyZW9yZGVyKHNhbXBsZSxkcGx5cjo6ZGVzYyhzYW1wbGUpKSx0b3RhbC8xZTYsZmlsbD1jaHIpKSArCiMgIHRoZW1lX2xpbmVkcmF3KCkgKyBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgY29vcmRfZmxpcCgpICsKIyAgeGxhYigic2FtcGxlIikgKyB5bGFiKCJtaWxsaW9uIHJlYWRzIikgKyBnZ3NjaTo6c2NhbGVfZmlsbF9pZ3YoKSArCiMgIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gcmV2KGxldmVscyhzYW1wbGUpKSkKYGBgCgojIyMjIEJpb3R5cGUKCmBgYHtyIGJpb3R5cGUsZmlnLndpZHRoPTgsZmlnLmhlaWdodD03fQpidCA8LSBtYXQgJT4lIHNlbGVjdCgtYygxLDIsNCkpICU+JSBncm91cF9ieShiaW90eXBlKSAlPiUKICBzdW1tYXJpc2VfYWxsKHN1bSkgJT4lIGZpbHRlcl9hdCgtMSxhbnlfdmFycyguID4gMTAwMCkpCmJ0ICU+JSB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcygiYmlvdHlwZSIpICU+JQogIGFzLm1hdHJpeCAlPiUgdCAlPiUgbW9zYWljcGxvdChsYXM9MixzaGFkZT1UUlVFKQpgYGAKCiMjIyBDb3JyZWxhdGlvbnMKCmRyb3Agcm93cyB3aXRoIGFsbCAwIC0+ICsxLzIgLT4gZ2VvbS5zY2FsZSAtPiBsb2cgLT4gUGVhcnNvbidzCgpgYGB7ciBtYWtlbWF0LCBmaWcud2lkdGg9OCxmaWcuaGVpZ2h0PTd9Cm1hdGYgPC0gbWF0ICU+JSBmaWx0ZXIoY2hyIT0iTVQiKSAlPiUgZmlsdGVyX2F0KC0oMTo0KSxhbnlfdmFycyguID4gMCkpClggPC0gbWF0ZiAlPiUgc2VsZWN0KC0oMTo0KSkgJT4lIGFzLm1hdHJpeApyb3duYW1lcyhYKSA8LSBtYXRmJGVuc19nZW5lCmxYIDwtIGxvZyhnc2NhbGUoWCswLjUpKQpSIDwtIGNvcihsWCk7IGRpYWcoUikgPC0gTkEKcGhlYXRtYXA6OnBoZWF0bWFwKFIsY29sb3I9dmlyaWRpczo6dmlyaWRpcygyNTYpKQpgYGAKCiMjIyBEaW1lbnNpb24gcmVkdWN0aW9uCgpgYGB7ciBQQ0EsZmlnLndpZHRoPTQsZmlnLmhlaWdodD0zfQojIHNldCBzY2FsZT1UUlVFIGlmIHRoZSBwYXR0ZXJucyAobm90IGxldmVsKSBpcyB0aGUgbWF0dGVyCnAgPC0gcHJjb21wKHQobFhbcmFuaygtYXBwbHkobFgsMSx2YXIpKSA8PSBudG9wLF0pLHNjYWxlPXNjYWxlcm93cyxjZW50ZXI9VFJVRSkKc2NyZWVwbG90KHAsbGFzPTIsbWFpbj0iSW1wb3J0YW5jZSIpCnByaW50KHN1bW1hcnkocCkkaW1wWyxzZXEobWluKDEwLG5jb2woWCkpKV0pCmBgYAoKYGBge3IgbWFrZXNjb3JlREZ9CmxhYmVsIDwtIGRlZiAlPiUgZmlsdGVyKHNhbXBsZSAlaW4lIGNvbG5hbWVzKFgpKQpkZiA8LSBkYXRhLmZyYW1lKHAkeCkgJT4lIGFzX3RpYmJsZShyb3duYW1lcz0ic2FtcGxlIikgJT4lCiAgaW5uZXJfam9pbihsYWJlbCwuKSAlPiUgc2VsZWN0KC1maWxlKQoKcHJpbnQoZGYpCmBgYAoKYGBge3IgcHJveGltaXR5LGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9NH0KZ2dwb2ludHMoZGYsbW9kaWZ5TGlzdChhZXMoUEMxLFBDMiksbXlhZXMpKQpnZ3BvaW50cyhkZixtb2RpZnlMaXN0KGFlcyhQQzIsUEMzKSxteWFlcykpCgpzZXQuc2VlZChzZWVkKQp1bSA8LSB1d290Ojp1bWFwKHAkeCxuX25laSwyKQpkZiA8LSBhc190aWJibGUodW0pICU+JSByZW5hbWUoVU1BUDE9VjEsVU1BUDI9VjIpICU+JSBiaW5kX2NvbHMoZGYpCmdncG9pbnRzKGRmLG1vZGlmeUxpc3QoYWVzKFVNQVAxLFVNQVAyKSxteWFlcykpCgpwcmludChkZikKcmVhZHI6OndyaXRlX2NzdihkZiwiQ0VMMDM4Nm5vdW1pX0MyQzEyX0NvdW50X1BDQV9maW4yMDA5MTUuY3N2IikKYGBgCgojIyMgREVTZXEyCgojIyMjIEZpdCBtb2RlbAoKYGBge3IgZGVzZXEyfQpkZHMgPC0gREVTZXEyOjpERVNlcURhdGFTZXRGcm9tTWF0cml4KFhbLGxhYmVsJHNhbXBsZV0sbGFiZWwsbW9kZWwpCmRkcyA8LSBERVNlcTI6OkRFU2VxKGRkcykKCiM9PT09PSMKIyAyMDE5MTIxM+i/veWKoApkZHMgPC0gREVTZXEyOjplc3RpbWF0ZVNpemVGYWN0b3JzKGRkcykKbm9ybSA8LSBERVNlcTI6OmNvdW50cyhkZHMsbm9ybWFsaXplZD1UUlVFKSAjREVH44KS5Y+W44Gj44Gf5b6M44Gu44Kv44Op44K544K/44Oq44Oz44Kw44Gr5L2/44GG44CCCgpub3JtYWxpemVkY291bnQgPC0gYXMuZGF0YS5mcmFtZShub3JtKSAlPiUgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oImVuc19nZW5lIikgJT4lIGFzX3RpYmJsZQpyZWFkcjo6d3JpdGVfY3N2KG5vcm1hbGl6ZWRjb3VudCwgIi4vQ0VMMDM4Nm5vdW1pX0MyQzEyX0gzbW0xOF9ub3JtQ291bnRfZmluMjAwOTE1LmNzdiIpCgpub3JtYWxpemVkY291bnQgJT4lIGlubmVyX2pvaW4oZTJnLCBieSA9ICJlbnNfZ2VuZSIpICU+JSByZWFkcjo6d3JpdGVfY3N2KCIuL0NFTDAzODZub3VtaV9DMkMxMl9ub3JtQ291bnRfZ2VuZW5hbWVfZmluMjAwOTE1LmNzdiIpCgojIyMjLS0tICsgc2l6ZSBmYWN0b3JzIOOCkuabuOOBjeWHuuOBlyAtLS0tLS0tLS0tLS0tLS0tLS0jIyMjCmFzLmRhdGEuZnJhbWUoREVTZXEyOjpzaXplRmFjdG9ycyhkZHMpKSAgJT4lIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCJzYW1wbGUiKSAlPiUgcmVhZHI6OndyaXRlX2NzdigiLi9DRUwwMzg2bm91bWlfQzJDMTJfSDNtbTE4X3NpemVmYWN0b3JzX2ZpbjIwMDkxNV9maW4yMDA5MTUuY3N2IikKYXMuZGF0YS5mcmFtZShERVNlcTI6OnNpemVGYWN0b3JzKGRkcykpICAlPiUgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oInNhbXBsZSIpIAoKI2NvdW50X2RkcyA8LSBlc3RpbWF0ZVNpemVGYWN0b3JzKGRkcykKI2NvdW50cyhjb3VudF9kZHMsIG5vcm1hbGl6ZWQ9VFJVRSkKYGBgCgoKdnN0ID0+IHogc2NvcmUgKDIwMDkxNGFkZCkKCmBgYHtyIHpzY29yZSAyMDA4MTFhZGR9CgojIyAyMDIwMDkxNAoKdnNkIDwtIERFU2VxMjo6dnN0KGRkcykgI25vcm1hbGl6ZWQgY291bnTjgYzlhaXjgaPjgabjgYTjgovjgIIodnN044GLcmxvZykKWGQgPC0gU3VtbWFyaXplZEV4cGVyaW1lbnQ6OmFzc2F5KHZzZCkgIyDlhajjgabpgbjmip4oMjAwMzI2KSAyMDE5MDkyMOOCkuWFg+OBqyAoMTkxMDI0KQpYcyA8LSBYZCAlPiUgdCAlPiUgc2NhbGUgJT4lIHQKCnZzdF9zY29yZSA8LSBYZCAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiZW5zX2dlbmUiKSAlPiUgYXNfdGliYmxlICMyMDA5MDkgYWRkCnZzdF90eXBlIDwtIHZzdF9zY29yZSAgJT4lIGFubm90YXRlICU+JSBkcGx5cjo6c2VsZWN0KCJlbnNfZ2VuZSIsImV4dF9nZW5lIiwgImJpb3R5cGUiLCJjaHIiLCBhbGxfb2YobGFiZWwkc2FtcGxlKSkKCgp6c2NvcmUgPC0gWHMgJT4lIGFzLmRhdGEuZnJhbWUoKSAlPiUgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oImVuc19nZW5lIikgJT4lIGFzX3RpYmJsZQp6c2NvcmVfdHlwZSA8LSB6c2NvcmUgICU+JSBhbm5vdGF0ZSAlPiUgZHBseXI6OnNlbGVjdCgiZW5zX2dlbmUiLCJleHRfZ2VuZSIsICJiaW90eXBlIiwiY2hyIiwgYWxsX29mKGxhYmVsJHNhbXBsZSkpCgpyZWFkcjo6d3JpdGVfY3N2KHZzdF9zY29yZSwgIkNFTDAzODZub3VtaV9DMkMxMl9IM21tMThfX3ZzdF9hbGxfZmluMjAwOTE1LmNzdiIpICMyMDA5MDkgYWRkCnJlYWRyOjp3cml0ZV9jc3YodnN0X3R5cGUsICJDRUwwMzg2bm91bWlfQzJDMTJfSDNtbTE4X192c3RfdHlwZV9hbGxfZmluMjAwOTE1LmNzdiIpICMyMDA5MDkgYWRkCnJlYWRyOjp3cml0ZV9jc3YoenNjb3JlLCAiQ0VMMDM4Nm5vdW1pX0MyQzEyX0gzbW0xOF9fenNjb3JlX2FsbF9maW4yMDA5MTUuY3N2IikKcmVhZHI6OndyaXRlX2Nzdih6c2NvcmVfdHlwZSwgIkNFTDAzODZub3VtaV9DMkMxMl9IM21tMThfX3pzY29yZV90eXBlX2FsbF9maW4yMDA5MTUuY3N2IikKCgpjb2xuYW1lcyh6c2NvcmVfdHlwZSkKbmNvbCh2c3RfdHlwZSkKbmNvbCh6c2NvcmVfdHlwZSkKbnJvdyh2c3RfdHlwZSkKbnJvdyh6c2NvcmVfdHlwZSkKCmBgYAoKCgpgYGB7ciBzYXZlIGNvZWZ9CmNvZWZfZGRzIDwtIGNvZWYoZGRzKSAlPiUgYXMuZGF0YS5mcmFtZSgpICU+JSB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiZW5zX2dlbmUiKSAlPiUgYXNfdGliYmxlCgpyZWFkcjo6d3JpdGVfY3N2KGNvZWZfZGRzLCAiQ0VMMDM4Nm5vdW1pX0MyQzEyX0gzbW0xOF9fY29lZnNfZmluMjAwOTE1LmNzdiIpCmBgYAoKCgojIyMjIERpYWdub3N0aWNzIHBsb3QKCmBgYHtyIGRpYWdub3N0aWNzLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9NX0KREVTZXEyOjpzaXplRmFjdG9ycyhkZHMpICU+JQogIHt0aWJibGUoc2FtcGxlPW5hbWVzKC4pLHNpemVGYWN0b3I9Lil9ICU+JQogIGdncGxvdChhZXMoc2FtcGxlLHNpemVGYWN0b3IpKSArIHRoZW1lX21pbmltYWwoKSArCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSArIGNvb3JkX2ZsaXAoKQpERVNlcTI6OnBsb3REaXNwRXN0cyhkZHMpCmBgYAoKIyMjIyBFeHRyYWN0IHJlc3VsdHMKCmBgYHtyIGV4dHJhY3RSZXN9CiNyZXMgPC0gbWFwcGx5KGZ1bmN0aW9uKHgpCiMgIERFU2VxMjo6cmVzdWx0cyhkZHMseCxsZmNUaHJlc2hvbGQ9bGZjdGhyZXRoLGFscGhhPWZkcikKIyxjb250cmFzdCkKCnJlcyA8LSBtYXBwbHkoZnVuY3Rpb24oeCkKICBERVNlcTI6OnJlc3VsdHMoZGRzLHgsbGZjVGhyZXNob2xkPWxmY3RocmV0aCxhbHBoYT1mZHIpCixjb250cmFzdCkKCgojIDIwMDkxNOS/ruatowpyZV9hbGwgPC0gbWFwKHJlcyxhc190aWJibGUscm93bmFtZXM9ImVuc19nZW5lIikgJT4lCiAgdGliYmxlKGFzcGVjdD1mYWN0b3IobmFtZXMoLiksbmFtZXMoLikpLGRhdGE9LikgJT4lCiAgbXV0YXRlKGRhdGE9bWFwKGRhdGEsYW5ub3RhdGUpKSAlPiUKICB1bm5lc3QoY29scyA9ICJkYXRhIikKCnJlIDwtIHJlX2FsbCAlPiUgZmlsdGVyKHBhZGo8ZmRyKSAjMTkxMTIw5L+u5q2jIHVubmVzdCgpIAoKCiNyZSA8LSBtYXAocmVzLGFzX3RpYmJsZSxyb3duYW1lcz0iZW5zX2dlbmUiKSAlPiUKIyAgdGliYmxlKGFzcGVjdD1mYWN0b3IobmFtZXMoLiksbmFtZXMoLikpLGRhdGE9LikgJT4lCiMgIG11dGF0ZShkYXRhPW1hcChkYXRhLGFubm90YXRlKSkgJT4lCiMgIHVubmVzdChjb2xzID0gImRhdGEiKSAlPiUgZmlsdGVyKHBhZGo8ZmRyKSAgIzE5MTEyMOS/ruatoyB1bm5lc3QoKSAKCmZjIDwtIHJlICU+JSBzZWxlY3QoMTo3KSAlPiUgc3ByZWFkKGFzcGVjdCxsb2cyRm9sZENoYW5nZSxmaWxsPTApCgppbWFwKHJlcyx+ewogIGNhdChwYXN0ZTAoIi0tICIsLnksIiAtLSIpKQogIERFU2VxMjo6c3VtbWFyeSgueCkgIzE5MTEyMOS/ruatoyBERVNlcTI6OnN1bW1hcnkuREVTZXFSZXN1bHRzKC54KQp9KSAlPiUgaW52aXNpYmxlCgpgYGAKCiMjIyBXcml0ZS1vdXQgdGFibGVzCgpgYGB7ciB3cml0ZW91dH0KaWYoZXhpc3RzKCJmYyIpKSAgIHJlYWRyOjp3cml0ZV9jc3YoZmMsIi4vMmd1bi9Jd2FzYWtpXzAzODZyZV9DMkMxMl9IM21tMThfbm91bWlfbDJmY19fZmluYWwyMDA5MTUuY3N2IikKaWYoZXhpc3RzKCJyZSIpKSAgIHJlYWRyOjp3cml0ZV9jc3YocmUsIi4vMmd1bi9Jd2FzYWtpXzAzODZyZV9DMkMxMl9IM21tMThfbm91bWlfcmVzdWx0c19fZmluYWwyMDA5MTUuY3N2IikKaWYoZXhpc3RzKCJyZV9hbGwiKSkgICByZWFkcjo6d3JpdGVfY3N2KHJlX2FsbCwiLi8yZ3VuL0l3YXNha2lfMDM4NnJlX0MyQzEyX0gzbW0xOF9ub3VtaV9yZXN1bHRzYWxsX19maW5hbDIwMDkxNS5jc3YiKQpgYGAKCkRFU2Vx44GubG9nMkZD44Gu6KiI566X44Gr44Gk44GE44GmIChjb2VmX2Rkc+OBi+OCieioiOeul+OBmeOCi+aWueazlSkKKDIwMjAwOTE15qSc6Ki8KQoKYGBge3IgY29lZl9kZHNsb2cyRkN9CgojIGxvZzJGQwpyZSAlPiUgZmlsdGVyKGFzcGVjdD09Imdyb3VwX0dfbW0xOEJfdnNfZUdGUCIpICU+JSBmaWx0ZXIoZW5zX2dlbmUgJWluJSBjKCJFTlNNVVNHMDAwMDAwODgyNTIiLCJFTlNNVVNHMDAwMDAwMjQ3NTQiLCJFTlNNVVNHMDAwMDAwMjQ2NDYiLCJFTlNNVVNHMDAwMDAwMzI3NDEiLCJFTlNNVVNHMDAwMDAwMzE4ODUiKSkKCgpyZSAlPiUgZmlsdGVyKGFzcGVjdD09Imdyb3VwX0Q3Ml9tbTE4Ql92c19lR0ZQIikgJT4lIGZpbHRlcihlbnNfZ2VuZSAlaW4lIGMoIkVOU01VU0cwMDAwMDA4ODI1MiIsIkVOU01VU0cwMDAwMDAyNDc1NCIsIkVOU01VU0cwMDAwMDAyNDY0NiIsIkVOU01VU0cwMDAwMDAzMjc0MSIsIkVOU01VU0cwMDAwMDAzMTg4NSIpKQoKIyBjb2Vm44GL44KJ5YaN54++44CAKOW8leOBjeeul+OCkuOBmeOCi+OBoOOBkeOBp+iJr+OBhCkKZGRkZGRkIDwtIGNvZWZfZGRzICU+JSBmaWx0ZXIoZW5zX2dlbmUgJWluJSBjKCJFTlNNVVNHMDAwMDAwODgyNTIiLCJFTlNNVVNHMDAwMDAwMjQ3NTQiLCJFTlNNVVNHMDAwMDAwMjQ2NDYiLCJFTlNNVVNHMDAwMDAwMzI3NDEiLCJFTlNNVVNHMDAwMDAwMzE4ODUiKSkKZGRkZGRkICU+JSBtdXRhdGUoLWdyb3VwX2VHRlBfR192c19tbTE4Ql9HLCBncm91cF9tbTE4Ql9ENzJfdnNfbW0xOEJfRy1ncm91cF9lR0ZQX0Q3Ml92c19tbTE4Ql9HKQoKYGBgCgojIyMgTUFwbG90CgpgYGB7ciB3cml0ZW91dCBtYXBsb3R9CgojIyBHcm93dGggIyMKCiNtYXBsb3QgPC0gREVTZXEyOjpwbG90TUEocmVzJGdyb3VwX0dfbW0xOEJfdnNfZUdGUCwgeWxpbT1jKC02LDYpKQojcHJpbnQobWFwbG90KQoKbWFwbG90IDwtIERFU2VxMjo6cGxvdE1BKHJlcyRncm91cF9HX21tMThCX3ZzX2VHRlAsIHlsaW09YygtNCw0KSxtYWluPSJHIG1tMThCIHZzIGVHRlAiKQpwcmludChtYXBsb3QpCm1hcGxvdCA8LSBERVNlcTI6OnBsb3RNQShyZXMkZ3JvdXBfR19tbTE4Ql92c19lR0ZQLCB5bGltPWMoLTUsNSksbWFpbj0iRyBtbTE4QiB2cyBlR0ZQIikKcHJpbnQobWFwbG90KQoKI21hcGxvdCA8LSBERVNlcTI6OnBsb3RNQShyZXMkZ3JvdXBfR19tbTE4Ql92c19lR0ZQLCB5bGltPWMoLTIsMikpCiNwcmludChtYXBsb3QpCgoKIyMgRDcyICMjCgojbWFwbG90IDwtIERFU2VxMjo6cGxvdE1BKHJlcyRncm91cF9ENzJfbW0xOEJfdnNfZUdGUCwgeWxpbT1jKC02LDYpKQojcHJpbnQobWFwbG90KQoKbWFwbG90IDwtIERFU2VxMjo6cGxvdE1BKHJlcyRncm91cF9ENzJfbW0xOEJfdnNfZUdGUCwgeWxpbT1jKC00LDQpLG1haW49IkQ3MiBtbTE4QiB2cyBlR0ZQIikKcHJpbnQobWFwbG90KQptYXBsb3QgPC0gREVTZXEyOjpwbG90TUEocmVzJGdyb3VwX0Q3Ml9tbTE4Ql92c19lR0ZQLCB5bGltPWMoLTUsNSksbWFpbj0iRDcyIG1tMThCIHZzIGVHRlAiKQpwcmludChtYXBsb3QpCgojbWFwbG90IDwtIERFU2VxMjo6cGxvdE1BKHJlcyRncm91cF9ENzJfbW0xOEJfdnNfZUdGUCwgeWxpbT1jKC0yLDIpKQojcHJpbnQobWFwbG90KQoKYGBgCgrjgZPjgaHjgonjgafmqKrou7jjgpLoqIjnrpfjgZfjgabjg5fjg63jg4Pjg4gKMjAyMDA5MTRhZGQgKDIwMjAwOTE1dmVyKQoKYGBge3Igbm9ybSBjb3VudCBkZWYgdGFibGV9CgpTZXRfY3V0b2ZmIDwtIDEwLjAKCiMjIOWQhOaZguWIu+OBruW5s+Wdh+OCkuioiOeul+OBl+OAgW5vcm1hbGl6ZWQgY291bnQgPiAxMCDjgpLotoXjgYjjgovjgoLjga7jgpLmir3lh7rjgZnjgovjgIIKCiMtLS0tLSDkvb/nlKjjgZnjgovjg4fjg7zjgr/jga7jgb/lj5bjgorlh7rjgZkgLS0tIyAyMDIwMDkxNApub3JtX3Bsb3RsaXN0X2FsbCA8LSBub3JtYWxpemVkY291bnQgJT4lIGdhdGhlcigic2FtcGxlIiwgIm5vcm1hbGl6ZWQiLC0oZW5zX2dlbmUpKSAlPiUgaW5uZXJfam9pbihkZWYsIGJ5ID0gInNhbXBsZSIpICU+JSBtdXRhdGUodGltZT1mYWN0b3IodGltZSwgYygiRyIsIkQ3MiIpKSklPiUgbXV0YXRlKHR5cGU9ZmFjdG9yKHR5cGUsYygibW0xOEIiLCJlR0ZQIikpKSAlPiUgbXV0YXRlKGdyb3VwPWZhY3Rvcihncm91cCxjKCJlR0ZQX0ciLCJtbTE4Ql9HIiwiZUdGUF9ENzIiLCAibW0xOEJfRDcyIikpKQoKI25vcm1fcGxvdGxpc3Rfc2VsIDwtIG5vcm1fcGxvdGxpc3RfYWxsICU+JSBmaWx0ZXIoc2FtcGxlICVpbiUgZGVmX3NlbGVjdCRzYW1wbGUpICU+JSBtdXRhdGUodGltZT1mYWN0b3IodGltZSwgYygiRyIsIkQ3MiIpKSklPiUgbXV0YXRlKHR5cGU9ZmFjdG9yKHR5cGUsYygiZUdGUCIsIm1tMThCIikpKSAlPiUgbXV0YXRlKGdyb3VwPWZhY3Rvcihncm91cCxjKCJlR0ZQX0ciLCJtbTE4Ql9HIiwiZUdGUF9ENzIiLCAibW0xOEJfRDcyIikpKQoKI25vdG1fcGxvdGxpc3RfY3V0b2ZmIDwtIG5vcm1fcGxvdGxpc3RfYWxsICU+JSBhbm5vdGF0ZSgpICU+JSBncm91cF9ieShlbnNfZ2VuZSwgZXh0X2dlbmUsIERheSwgaW50YWN0X0NUWCkgJT4lIHN1bW1hcmlzZShncm91cE1lYW49bWVhbihub3JtYWxpemVkKSkgICU+JSB1bmdyb3VwKCkgJT4lIGRwbHlyOjpzZWxlY3QoZW5zX2dlbmUsIGV4dF9nZW5lKSAlPiUgdW5pcXVlKCkKCiMjICJlR0ZQIiwibW0xOEIi6Zai5L+C44Gq44GP5bmz5Z2H44KS5rGC44KB44KLCm5vdG1fcGxvdGxpc3RfYmVmb3JlY3V0b2ZmIDwtIG5vcm1fcGxvdGxpc3RfYWxsICU+JSBhbm5vdGF0ZSgpICU+JSBncm91cF9ieShlbnNfZ2VuZSwgZXh0X2dlbmUsIHRpbWUpICU+JSBzdW1tYXJpc2UoZ3JvdXBNZWFuPW1lYW4obm9ybWFsaXplZCkpCiNub3RtX3Bsb3RsaXN0X2JlZm9yZWN1dG9mZiA8LSBub3JtX3Bsb3RsaXN0X3NlbCAlPiUgYW5ub3RhdGUoKSAlPiUgZ3JvdXBfYnkoZW5zX2dlbmUsIGV4dF9nZW5lLCB0aW1lKSAlPiUgc3VtbWFyaXNlKGdyb3VwTWVhbj1tZWFuKG5vcm1hbGl6ZWQpKQoKbm90bV9wbG90bGlzdF9jdXRvZmYgPC0gbm90bV9wbG90bGlzdF9iZWZvcmVjdXRvZmYgJT4lIGZpbHRlcihncm91cE1lYW4gPiBTZXRfY3V0b2ZmKSAlPiUgdW5ncm91cCgpICU+JSBkcGx5cjo6c2VsZWN0KGVuc19nZW5lLCBleHRfZ2VuZSkgJT4lIHVuaXF1ZSgpCgpucm93KG5vdG1fcGxvdGxpc3RfYmVmb3JlY3V0b2ZmICU+JSB1bmdyb3VwKCkgJT4lIGRwbHlyOjpzZWxlY3QoZW5zX2dlbmUsIGV4dF9nZW5lKSAlPiUgdW5pcXVlKCkpICPjgZPjga7lgKTjgpJNQXBsb3Tjga546Lu444Gr5L2/55SoCm5yb3cobm90bV9wbG90bGlzdF9jdXRvZmYpICPop6PmnpDlr77osaHjgpLntZ7jgovjgIAo5b6M44Gu5YWo5L2T44Gu44Kv44Op44K544K/44Oq44Oz44Kw44Gr5L2/55SoKQoKCmBgYAoKYGBge3Igbm9ybV9wbG90bGlzdF9hbGx9Cgpub3JtX3Bsb3RsaXN0X2FsbCAlPiUgcmVhZHI6OndyaXRlX2NzdigiTm9ybV9kZWZ0YWJsZV9hbGxfZmluYWwyMDA5MTUuY3N2IikKI25vcm1fcGxvdGxpc3Rfc2VsICU+JSByZWFkcjo6d3JpdGVfY3N2KCJOb3JtX2RlZnRhYmxlX3NlbGVjdF9maW5hbDIwMDkxNS5jc3YiKSAj44GT44KM44KSTUFwbG9044Gr5L2/55So44GZ44KLCm5vdG1fcGxvdGxpc3RfYmVmb3JlY3V0b2ZmICU+JSByZWFkcjo6d3JpdGVfY3N2KCJOb3JtX2dyb3VwTWVhbl9zZWxlY3RfZmluYWwyMDA5MTUuY3N2IikKbm90bV9wbG90bGlzdF9jdXRvZmYgICU+JSByZWFkcjo6d3JpdGVfY3N2KCJOb3JtX2dyb3VwTWVhbl9zZWxlY3RfY3V0b2ZmMTBfZmluYWwyMDA5MTUuY3N2IikKCm5yb3cobm9ybV9wbG90bGlzdF9hbGwpCiNucm93KG5vcm1fcGxvdGxpc3Rfc2VsKQpucm93KG5vdG1fcGxvdGxpc3RfYmVmb3JlY3V0b2ZmKQpucm93KG5vdG1fcGxvdGxpc3RfY3V0b2ZmKQoKYGBgCgoKYGBge3IgbWFwbG90IGRyYXcsIGZpZy53aWR0aCA9IDcsIGZpZy5oZWlnaHQgPSA4fQoKcmVfc2VsZWN0X3Bsb3QgPC0gcmVfYWxsICU+JSBmaWx0ZXIoYXNwZWN0ICVpbiUgYygiZ3JvdXBfR19tbTE4Ql92c19lR0ZQIiwiZ3JvdXBfRDcyX21tMThCX3ZzX2VHRlAiKSkgJT4lIG11dGF0ZSh0aW1lPWNhc2Vfd2hlbihhc3BlY3Q9PSJncm91cF9HX21tMThCX3ZzX2VHRlAifiJHIixhc3BlY3Q9PSJncm91cF9ENzJfbW0xOEJfdnNfZUdGUCJ+IkQ3MiIsVFJVRSB+ICJGQUxTRSIpKSAgJT4lIGxlZnRfam9pbihub3RtX3Bsb3RsaXN0X2JlZm9yZWN1dG9mZikgJT4lIG11dGF0ZSh0aW1lPWZhY3Rvcih0aW1lLCBjKCJHIiwiRDcyIikpKQoKcmVfc2VsZWN0X3Bsb3QgJT4lIHJlYWRyOjp3cml0ZV9jc3YoIi4vTUFwbG90L0MyQzEyX21tMThCX3ZzX2VHRlBfREVHX3RpbWVfTUFwbG90ZGF0YS5jc3YiKQoKIyMjIwoKRGF5bWVhbiA8LSByZV9zZWxlY3RfcGxvdCAlPiUgZ3JvdXBfYnkodGltZSkgJT4lIHN1bW1hcmlzZShEYXlNZWFuPW1lYW4oZ3JvdXBNZWFuKSkKTWVhbl9jb2xvciA8LSAiI0I4ODYwQiIKCkRheW1lYW4KCkFsbGdlbmVfbnVtIDwtIHJlX3NlbGVjdF9wbG90ICU+JSBkcGx5cjo6c2VsZWN0KGVuc19nZW5lKSAlPiUgdW5pcXVlKCkgJT4lIG5yb3coKQoKCmBgYAoKCgpgYGB7ciBNQXBsb3QgREVHcywgZmlnLndpZHRoID0gNiwgZmlnLmhlaWdodCA9IDh9CgpmX0RFR19pbiA8LSBmdW5jdGlvbih4KSB4ICU+JSBmaWx0ZXIocGFkajwwLjEpCmZfREVHX291dCA8LSBmdW5jdGlvbih4KSB4ICU+JSBmaWx0ZXIoKCEocGFkajwwLjEpKXxpcy5uYShwYWRqKSkKCgpmX2luRkNfZGVnaW4gPC0gZnVuY3Rpb24oeCkgeCAlPiUgZl9ERUdfaW4gJT4lIGZpbHRlcighKGFicyhsb2cyRm9sZENoYW5nZSkgPiA1LjApKQpmX2luRkNfZGVnb3V0IDwtIGZ1bmN0aW9uKHgpIHggJT4lIGZfREVHX291dCAlPiUgZmlsdGVyKCEoYWJzKGxvZzJGb2xkQ2hhbmdlKSA+IDUuMCkpCgpmX292ZXJGQ191cF9kZWdpbiA8LSBmdW5jdGlvbih4KSB4ICU+JSBmX0RFR19pbiAlPiUgZmlsdGVyKGxvZzJGb2xkQ2hhbmdlID4gNS4wKSAlPiUgbXV0YXRlKGxvZzJGb2xkQ2hhbmdlPTUuMCkgCmZfb3ZlckZDX2Rvd25fZGVnaW4gPC0gZnVuY3Rpb24oeCkgeCAlPiUgZl9ERUdfaW4gJT4lIGZpbHRlcihsb2cyRm9sZENoYW5nZSA8IC01LjApICU+JSBtdXRhdGUobG9nMkZvbGRDaGFuZ2U9LTUuMCkKZl9vdmVyRkNfdXBfZGVnb3V0IDwtIGZ1bmN0aW9uKHgpIHggJT4lIGZfREVHX291dCAlPiUgZmlsdGVyKGxvZzJGb2xkQ2hhbmdlID4gNS4wKSAlPiUgbXV0YXRlKGxvZzJGb2xkQ2hhbmdlPTUuMCkKZl9vdmVyRkNfZG93bl9kZWdvdXQgPC0gZnVuY3Rpb24oeCkgeCAlPiUgZl9ERUdfb3V0ICU+JSBmaWx0ZXIobG9nMkZvbGRDaGFuZ2UgPCAtNS4wKSAlPiUgbXV0YXRlKGxvZzJGb2xkQ2hhbmdlPS01LjApCgoKIyMjIOWFqOOBpgpyZV9zZWxlY3RfcGxvdCAlPiUgZ3JvdXBfYnkoYXNwZWN0KSAlPiUgc3VtbWFyaXNlKG4oKSkKCiMjIyBERUcKcmVfc2VsZWN0X3Bsb3QgJT4lIGZfREVHX2luICU+JSBncm91cF9ieShhc3BlY3QpICU+JSBzdW1tYXJpc2UobigpKQpyZV9zZWxlY3RfcGxvdCAlPiUgZl9pbkZDX2RlZ2luICU+JSBncm91cF9ieShhc3BlY3QpICU+JSBzdW1tYXJpc2UobigpKQpyZV9zZWxlY3RfcGxvdCAlPiUgZl9vdmVyRkNfdXBfZGVnaW4gJT4lIGdyb3VwX2J5KGFzcGVjdCkgJT4lIHN1bW1hcmlzZShuKCkpCnJlX3NlbGVjdF9wbG90ICU+JSBmX292ZXJGQ19kb3duX2RlZ2luICU+JSBncm91cF9ieShhc3BlY3QpICU+JSBzdW1tYXJpc2UobigpKQoKIyMjIERFRyDku6XlpJYKcmVfc2VsZWN0X3Bsb3QgJT4lIGZfREVHX291dCAlPiUgZ3JvdXBfYnkoYXNwZWN0KSAlPiUgc3VtbWFyaXNlKG4oKSkKcmVfc2VsZWN0X3Bsb3QgJT4lIGZfaW5GQ19kZWdvdXQgJT4lIGdyb3VwX2J5KGFzcGVjdCkgJT4lIHN1bW1hcmlzZShuKCkpCnJlX3NlbGVjdF9wbG90ICU+JSBmX292ZXJGQ191cF9kZWdvdXQgJT4lIGdyb3VwX2J5KGFzcGVjdCkgJT4lIHN1bW1hcmlzZShuKCkpCnJlX3NlbGVjdF9wbG90ICU+JSBmX292ZXJGQ19kb3duX2RlZ291dCAlPiUgZ3JvdXBfYnkoYXNwZWN0KSAlPiUgc3VtbWFyaXNlKG4oKSkKCmRkZGRkZGRkZCA8LSByZV9zZWxlY3RfcGxvdCAgJT4lIGZfREVHX2luICU+JSBtdXRhdGUoRkNfdXBkb3duID0gY2FzZV93aGVuKGxvZzJGb2xkQ2hhbmdlPjB+IlVwIiwgbG9nMkZvbGRDaGFuZ2U8MH4iRG93biIpKSAlPiUgbXV0YXRlKEZDX3VwZG93bj1mYWN0b3IoRkNfdXBkb3duLGMoIlVwIiwiRG93biIpKSkgJT4lIGFycmFuZ2UodGltZSxGQ191cGRvd24pCmVlZWVlZWVlZSA8LSBkZGRkZGRkZGQgICU+JSBncm91cF9ieShhc3BlY3QsdGltZSxGQ191cGRvd24pICU+JSBzdW1tYXJpc2UoY291bnQ9bigpKQoKCmdnZ2dsYWJlbCA8LSBwYXN0ZSgiQzJDMTIgbW0xOEJfdnNfZUdGUDoiLCBBbGxnZW5lX251bSwgImdlbmVzLCIsCiAgICAgICAgICAgICAgICAgICAiRzoiLGVlZWVlZWVlZSRGQ191cGRvd25bMV0sZWVlZWVlZWVlJGNvdW50WzFdLCIsIixlZWVlZWVlZWUkRkNfdXBkb3duWzJdLGVlZWVlZWVlZSRjb3VudFsyXSwKICAgICAgICAgICAgICAgICAgICIsIiwiRDcyOiIsZWVlZWVlZWVlJEZDX3VwZG93blszXSxlZWVlZWVlZWUkY291bnRbM10sIiwiLGVlZWVlZWVlZSRGQ191cGRvd25bNF0sZWVlZWVlZWVlJGNvdW50WzRdLHNlcD0iICIpCnByaW50KGdnZ2dsYWJlbCkKCiMjIyMjIwoKZ2dtYXBsb3QgPC0gcmVfc2VsZWN0X3Bsb3QgICU+JSAgZ2dwbG90KGFlcyhncm91cE1lYW4sbG9nMkZvbGRDaGFuZ2UpKStnZW9tX3BvaW50KHNpemU9MC4xLCBhbHBoYSA9IDAuNSxkYXRhPWZfREVHX291dCxjb2xvcj0iI2JkYmRiZCIpICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0PTAsc2xvcGU9MCxjb2xvdXI9ImJsYWNrIixzaXplPTAuMikgK2dlb21fcG9pbnQoYWVzKGdyb3VwTWVhbixsb2cyRm9sZENoYW5nZSksc2l6ZT0wLjEsY29sb3I9IiNmZjAwMDAiLCBkYXRhPWZfREVHX2luKSArIHNjYWxlX3hfbG9nMTAoKSArIHRoZW1lX2J3KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKyBnZ3RpdGxlKGdnZ2dsYWJlbCkgKyB5bGltKC01LjAsIDUuMCkgKyBmYWNldF93cmFwKH50aW1lLG5jb2w9MSkgKyB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSx2anVzdD0xLjApLCBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBzdHJpcC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE1KSxzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9NSkpCgojKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiI2ZmMDAwMCIsIiNmZjAwMDAiLCIjMDAwMDAwIikpIAoKZ2dzYXZlKGZpbGU9Ii4vTUFwbG90L0MyQzEyX21tMThCX3ZzX2VHRlBfREVHX3RpbWVfTUFwbG90LnBkZiIsIHBsb3QgPSBnZ21hcGxvdCwgd2lkdGggPSA2LCBoZWlnaHQgPSA4LCBkcGkgPSAxMjApCnBsb3QoZ2dtYXBsb3QpCgoKZ2dtYXBsb3QgPC0gcmVfc2VsZWN0X3Bsb3QgICU+JSAgZ2dwbG90KGFlcyhncm91cE1lYW4sbG9nMkZvbGRDaGFuZ2UpKStnZW9tX3BvaW50KHNpemU9MC4xLCBhbHBoYSA9IDAuNSxkYXRhPWZfREVHX291dCxjb2xvcj0iI2JkYmRiZCIpICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0PTAsc2xvcGU9MCxjb2xvdXI9ImJsYWNrIixzaXplPTAuMikgICsgZ2VvbV92bGluZShkYXRhID0gRGF5bWVhbiwgYWVzKHhpbnRlcmNlcHQ9RGF5TWVhbiksY29sb3VyPU1lYW5fY29sb3Isc2l6ZT0wLjIsbGluZXR5cGU9ImRhc2hlZCIpICtnZW9tX3BvaW50KGFlcyhncm91cE1lYW4sbG9nMkZvbGRDaGFuZ2UpLHNpemU9MC4xLGNvbG9yPSIjZmYwMDAwIiwgZGF0YT1mX0RFR19pbikgKyBzY2FsZV94X2xvZzEwKCkgKyB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgZ2d0aXRsZShnZ2dnbGFiZWwpICsgeWxpbSgtNS4wLCA1LjApICsgZmFjZXRfd3JhcCh+dGltZSxuY29sPTEpICsgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsdmp1c3Q9MS4wKSwgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Iiwgc3RyaXAudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNSksc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSx0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTUpKQoKIysgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiNmZjAwMDAiLCIjZmYwMDAwIiwiIzAwMDAwMCIpKSAKCmdnc2F2ZShmaWxlPSIuL01BcGxvdC9DMkMxMl9tbTE4Ql92c19lR0ZQX0RFR190aW1lX01BcGxvdF9NZWFuLnBkZiIsIHBsb3QgPSBnZ21hcGxvdCwgd2lkdGggPSA2LCBoZWlnaHQgPSA4LCBkcGkgPSAxMjApCnBsb3QoZ2dtYXBsb3QpCgojIyMjIyMKIyMgRkMgb3ZlcjXjgoLlh7rlipsKCgpnZ21hcGxvdCA8LSAgcmVfc2VsZWN0X3Bsb3QgICU+JSAgZ2dwbG90KGFlcyhncm91cE1lYW4sbG9nMkZvbGRDaGFuZ2UpKStnZW9tX3BvaW50KHNpemU9MC4xLCBhbHBoYSA9IDAuNSxkYXRhPWZfaW5GQ19kZWdvdXQsY29sb3I9IiNiZGJkYmQiKSArZ2VvbV9wb2ludChzaXplPTAuMiwgYWxwaGEgPSAwLjUsc2hhcGU9MixkYXRhPWZfb3ZlckZDX3VwX2RlZ291dCxjb2xvcj0iI2JkYmRiZCIpK2dlb21fcG9pbnQoc2l6ZT0wLjIsIGFscGhhID0gMC41LHNoYXBlPTYsZGF0YT1mX292ZXJGQ19kb3duX2RlZ291dCxjb2xvcj0iI2JkYmRiZCIpICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0PTAsc2xvcGU9MCxjb2xvdXI9ImJsYWNrIixzaXplPTAuMikgICtnZW9tX3BvaW50KGFlcyhncm91cE1lYW4sbG9nMkZvbGRDaGFuZ2UpLHNpemU9MC4xLGNvbG9yPSIjZmYwMDAwIiwgZGF0YT1mX2luRkNfZGVnaW4pICtnZW9tX3BvaW50KHNpemU9MC4zLCBzaGFwZT0yLGRhdGE9Zl9vdmVyRkNfdXBfZGVnaW4sY29sb3I9IiNmZjAwMDAiKSArZ2VvbV9wb2ludChzaXplPTAuMywgc2hhcGU9NixkYXRhPWZfb3ZlckZDX2Rvd25fZGVnaW4sY29sb3I9IiNmZjAwMDAiKSAgKyBzY2FsZV94X2xvZzEwKCkgKyB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgZ2d0aXRsZShnZ2dnbGFiZWwpICsgeWxpbSgtNS4wLCA1LjApICsgZmFjZXRfd3JhcCh+dGltZSxuY29sPTEpICsgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSxheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsdmp1c3Q9MS4wKSwgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Iiwgc3RyaXAudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNSksc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSx0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTUpKQoKZ2dzYXZlKGZpbGU9Ii4vTUFwbG90L0MyQzEyX21tMThCX3ZzX2VHRlBfREVHX3RpbWVfTUFwbG90X292ZXI1LnBkZiIsIHBsb3QgPSBnZ21hcGxvdCwgd2lkdGggPSA2LCBoZWlnaHQgPSA4LCBkcGkgPSAxMjApCnBsb3QoZ2dtYXBsb3QpCgoKZ2dtYXBsb3QgPC0gIHJlX3NlbGVjdF9wbG90ICAlPiUgIGdncGxvdChhZXMoZ3JvdXBNZWFuLGxvZzJGb2xkQ2hhbmdlKSkrZ2VvbV9wb2ludChzaXplPTAuMSwgYWxwaGEgPSAwLjUsZGF0YT1mX2luRkNfZGVnb3V0LGNvbG9yPSIjYmRiZGJkIikgK2dlb21fcG9pbnQoc2l6ZT0wLjIsIGFscGhhID0gMC41LHNoYXBlPTIsZGF0YT1mX292ZXJGQ191cF9kZWdvdXQsY29sb3I9IiNiZGJkYmQiKStnZW9tX3BvaW50KHNpemU9MC4yLCBhbHBoYSA9IDAuNSxzaGFwZT02LGRhdGE9Zl9vdmVyRkNfZG93bl9kZWdvdXQsY29sb3I9IiNiZGJkYmQiKSArIGdlb21fYWJsaW5lKGludGVyY2VwdD0wLHNsb3BlPTAsY29sb3VyPSJibGFjayIsc2l6ZT0wLjIpICArIGdlb21fdmxpbmUoZGF0YSA9IERheW1lYW4sIGFlcyh4aW50ZXJjZXB0PURheU1lYW4pLGNvbG91cj1NZWFuX2NvbG9yLHNpemU9MC4yLGxpbmV0eXBlPSJkYXNoZWQiKSArZ2VvbV9wb2ludChhZXMoZ3JvdXBNZWFuLGxvZzJGb2xkQ2hhbmdlKSxzaXplPTAuMSxjb2xvcj0iI2ZmMDAwMCIsIGRhdGE9Zl9pbkZDX2RlZ2luKSArZ2VvbV9wb2ludChzaXplPTAuMywgc2hhcGU9MixkYXRhPWZfb3ZlckZDX3VwX2RlZ2luLGNvbG9yPSIjZmYwMDAwIikgK2dlb21fcG9pbnQoc2l6ZT0wLjMsIHNoYXBlPTYsZGF0YT1mX292ZXJGQ19kb3duX2RlZ2luLGNvbG9yPSIjZmYwMDAwIikgICsgc2NhbGVfeF9sb2cxMCgpICsgdGhlbWVfYncoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArIGdndGl0bGUoZ2dnZ2xhYmVsKSArIHlsaW0oLTUuMCwgNS4wKSArIGZhY2V0X3dyYXAofnRpbWUsbmNvbD0xKSArIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNSksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LHZqdXN0PTEuMCksIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIHN0cmlwLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTUpLHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT01KSkKCmdnc2F2ZShmaWxlPSIuL01BcGxvdC9DMkMxMl9tbTE4Ql92c19lR0ZQX0RFR190aW1lX01BcGxvdF9NZWFuX292ZXI1LnBkZiIsIHBsb3QgPSBnZ21hcGxvdCwgd2lkdGggPSA2LCBoZWlnaHQgPSA4LCBkcGkgPSAxMjApCnBsb3QoZ2dtYXBsb3QpCgpgYGAKCgojIyMgR0/op6PmnpAgPGNsdXN0ZXJQcm9maWxlcj4KCjIwMTkxMjA06L+95YqgCm1vdXNlLCBDVFgsIDLnvqTplpMgKFVwLCBEb3duKSDjga7ntZDmnpxHT+OCkuWPguiAg+OBq+OAgiAoMTkxMTIwdmVyKQoKIyMjIyAy576k6ZaTIChVcCwgRG93bikg44Gu57WQ5p6c44KSR08KYGBge3IgR08gTG9hZCBsaXN0IHBhcnQzLTF9CgoKdGFibGVfZGVnY2x1c3RlciA8LSByZSAlPiUgZmlsdGVyKGFzcGVjdD09Imdyb3VwX0Q3Ml9tbTE4Ql92c19lR0ZQIikgJT4lIGFycmFuZ2UoZW5zX2dlbmUpICU+JSBkcGx5cjo6c2VsZWN0KGVuc19nZW5lLGV4dF9nZW5lLGxvZzJGb2xkQ2hhbmdlKQoKI2ZpbGVfZGVnY2x1c3RlciA8LSAiL2hvbWUvZ3Vlc3RBL283MDU3OGEvYWt1d2FrYWRvL2t1d2FrYWRvL3NjQ0VMU2VxMi9Jd2FzYWtpXzAzODZfQzJDMTJfSDNtbTE4L0ZpbmFsX0xhc3RfUnNlcnZlcl8yMDA1MjMvSXdhc2FraV8wMzg2cmVfQzJDMTJfSDNtbTE4X25vdW1pX3Jlc3VsdHNfX2ZpbmFsMjAwNTIzLmNzdiIKI3RhYmxlX2RlZ2NsdXN0ZXIgPC0gcmVhZHI6OnJlYWRfY3N2KGZpbGVfZGVnY2x1c3RlcikgJT4lIGZpbHRlcihhc3BlY3Q9PSJncm91cF9ENzJfbW0xOEJfdnNfZUdGUCIpICU+JSBhcnJhbmdlKGVuc19nZW5lKSAlPiUgZHBseXI6OnNlbGVjdChlbnNfZ2VuZSxleHRfZ2VuZSxsb2cyRm9sZENoYW5nZSkKCiMgcGx1cwp0YWJsZV9kZWdjbHVzdGVyICU+JSBmaWx0ZXIobG9nMkZvbGRDaGFuZ2U+MCkgJT4lIHN1bW1hcmlzZShwbHVzID0gZHBseXI6Om4oKSkKCiMgbWludXMKdGFibGVfZGVnY2x1c3RlciAlPiUgZmlsdGVyKGxvZzJGb2xkQ2hhbmdlPDApICU+JSBzdW1tYXJpc2UobWludXMgPSBkcGx5cjo6bigpKQoKIyMjIyMgRkRSIHNldHRpbmcgIyMjIyMjCmdvZmRyIDwtIDAuMQoKY2x1c3Rlcl9udW0gPC0gMgoKYGBgCgoyMDE5MTEwNuS/ruato+OCkuWPguiAg+OBqwpVcCBEb3du55SoCgooMjAyMDA5MTUsIGRlZmFsdOOBrkdP44GucGxvdOOBruiqv+WtkOOBjOaCquOBhCkKCmBgYHtyIGdvIGNsdXN0ZXJQcm9maWxlIHBhcnQzLTJ9CmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KG9yZy5NbS5lZy5kYikKCgojLS0tLS0tLS0tLS0tLSMKCmZpbGVuYW1lX2xpc3QgPC0gIi4vY2x1c3RlclByb2ZpbGUvSXdhc2FraV8wMzg2cmVfQzJDMTJfSDNtbTE4XzJndW5mZHIwcDFfbG9nMkZvbGRDaGFuZ2VfQlBmZHIwcDFfZ2VuZXJhdGlvXyIKZmlsZW5hbWVfY3N2IDwtICIuL2NsdXN0ZXJQcm9maWxlL0l3YXNha2lfMDM4NnJlX0MyQzEyX0gzbW0xOF8yZ3VuZmRyMHAxX2xvZzJGb2xkQ2hhbmdlX0JQZmRyMHAxX2dlbmVyYXRpb19VcERvd24iCgojLS0tLS0tLS0tLS0tLSMKCmNsdXN0ZXJfbGlzdCA8LSBhcy5saXN0KE5BKSAj5Yid5pyf5YyWCgpmb3IgKGkgaW4gMToyKSB7CiAgcHJlX2xpc3QgPC0gYXMubGlzdChOQSkgICPliJ3mnJ/ljJYKICAgCiAgaWYgKGkgPT0gMSkgeyAKICAgIHByZV9saXN0IDwtIHRhYmxlX2RlZ2NsdXN0ZXIgJT4lICBmaWx0ZXIobG9nMkZvbGRDaGFuZ2U+MCkgJT4lIGRwbHlyOjpzZWxlY3QoZW5zX2dlbmUpICU+JSBhcy5saXN0KCkKICAgICNwcmVfbGlzdCA8LSB0YWJsZV9kZWdjbHVzdGVyICU+JSBmaWx0ZXIobG9nMkZvbGRDaGFuZ2U9PSJVcCIpICU+JSBkcGx5cjo6c2VsZWN0KGVuc19nZW5lKSAlPiUgYXMubGlzdCgpCiAgICBuYW1lcyhwcmVfbGlzdCkgPC0gcGFzdGUoIkVOU0VNQkwiLGFzLmNoYXJhY3RlcigidXAiKSxzZXA9Il8iKQogIH0gCiAgZWxzZSB7IAogICAgcHJlX2xpc3QgPC0gdGFibGVfZGVnY2x1c3RlciAlPiUgIGZpbHRlcihsb2cyRm9sZENoYW5nZTwwKSAlPiUgZHBseXI6OnNlbGVjdChlbnNfZ2VuZSkgJT4lIGFzLmxpc3QoKQogICAgbmFtZXMocHJlX2xpc3QpIDwtIHBhc3RlKCJFTlNFTUJMIixhcy5jaGFyYWN0ZXIoImRvd24iKSxzZXA9Il8iKQogIH0KICAgCiAgaWYgKGkgPT0gMSkgeyAKICAgICBjbHVzdGVyX2xpc3QgPC0gcHJlX2xpc3QKICB9IAogIGVsc2UgY2x1c3Rlcl9saXN0IDwtIGMoY2x1c3Rlcl9saXN0LCBwcmVfbGlzdCkgCn0KCgoKZm9yIChpIGluIDE6MikgewogIHByaW50KHBhc3RlKGksIGNsdXN0ZXJfbGlzdFtbaV1dICU+JSB0aWJibGU6OmVuZnJhbWUobmFtZSA9IE5VTEwpICU+JSBucm93KCksIHNlcD0iLCAiKSkKICAjcHJpbnQocGFzdGUoaSwgY2x1c3Rlcl9saXN0W1tpXV0gJT4lIGFzX3RpYmJsZSgpICU+JSBucm93KCksIHNlcD0iLCAiKSkgI0NhbGxpbmcgYGFzX3RpYmJsZSgpYCBvbiBhIHZlY3RvciBpcyBkaXNjb3VyYWdlZCwgYmVjYXVzZSB0aGUgYmVoYXZpb3IgaXMgbGlrZWx5IHRvIGNoYW5nZSBpbiB0aGUgZnV0dXJlLiBVc2UgYHRpYmJsZTo6ZW5mcmFtZShuYW1lID0gTlVMTClgIGluc3RlYWQuCiAgIAogIHByZV9lZ29fQlAgPC0gZW5yaWNoR08oZ2VuZSA9IGNsdXN0ZXJfbGlzdFtbaV1dLAogICAgICAgICAgICAgICAgIE9yZ0RiID0gIm9yZy5NbS5lZy5kYiIsCiAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICdFTlNFTUJMJywKICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLAogICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLAogICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiAgPSBnb2ZkciwgcXZhbHVlQ3V0b2ZmICA9IDEuMCkKICAgCiAgICMjIHB2YWx1ZSA8IHF2YWx1ZSA8IHAuYWRqdXN0ICMjCiAgICMgcXZhbHVlQ3V0b2ZmICA9IDAuMyAgcXZhbHVlQ3V0b2ZmICA9IDAuMiAsIHF2YWx1ZUN1dG9mZiAgPSAxLjAKCiAgaWYgKGkgPT0gMSkgeyAKICAgICB0YWJsZV9lZ29fQlAgPC0gZGF0YS5mcmFtZShwcmVfZWdvX0JQKSAlPiUgbXV0YXRlKGNsdXN0ZXI9IlVwIikgICMg44Oq44K544OI5Z6L44GL44KJ44OH44O844K/44OV44Os44O844Og44G45aSJ5o+bCiAgICAgIy0tLS0gcGxvdCAtLS0jCiAgICAgI0JQcGxvdCA8LSBkb3RwbG90KHByZV9lZ29fQlAsIHNob3dDYXRlZ29yeT0zMCwgb3JkZXJCeSA9ICJDb3VudCIpICNjbHVzdGVyUHJvZmlsZSDjga7mqZ/og73jgaflm7PjgpLmj4/jgY8oMTkxMTA25L+u5q2jKSB3cm9uZyBvcmRlckJ5IHBhcmFtZXRlcjsgc2V0IHRvIGRlZmF1bHQgYG9yZGVyQnkgPSAieCJgCiAgICAgI3ByaW50KEJQcGxvdCkKICAgICAjZ2dzYXZlKEJQcGxvdCxmaWxlPXBhc3RlKGZpbGVuYW1lX2xpc3QsIlVwIiwiLnBuZyIsc2VwPSIiKSwgd2lkdGggPSA4LCBoZWlnaHQgPSAxMiwgZHBpID0gMTIwKQogIH0gCiAgZWxzZSB7CiAgICAgdGFibGVfZWdvX0JQIDwtIHRhYmxlX2Vnb19CUCAlPiUgYmluZF9yb3dzKGRhdGEuZnJhbWUocHJlX2Vnb19CUCkgJT4lIG11dGF0ZShjbHVzdGVyPSJEb3duIikpCiAgICAgIy0tLS0gcGxvdCAtLS0jCiAgICAgI0JQcGxvdCA8LSBkb3RwbG90KHByZV9lZ29fQlAsIHNob3dDYXRlZ29yeT0zMCwgb3JkZXJCeSA9ICJDb3VudCIpICNjbHVzdGVyUHJvZmlsZSDjga7mqZ/og73jgaflm7PjgpLmj4/jgY8oMTkxMTA25L+u5q2jKSB3cm9uZyBvcmRlckJ5IHBhcmFtZXRlcjsgc2V0IHRvIGRlZmF1bHQgYG9yZGVyQnkgPSAieCJgCiAgICAgI3ByaW50KEJQcGxvdCkKICAgICAjZ2dzYXZlKEJQcGxvdCxmaWxlPXBhc3RlKGZpbGVuYW1lX2xpc3QsIkRvd24iLCIucG5nIixzZXA9IiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDEyLCBkcGkgPSAxMjApCiAgfQp9CgoKCiMtLS0tLS0jCiMg44OH44O844K/44GvdGFibGVfZWdvX0JQ44Gr44CCCgoKCmBgYAoKYGBge3IgZ28gY2x1c3RlclByb2ZpbGUgcGFydDMtM30KcHJpbnQodGFibGVfZWdvX0JQICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgc3VtbWFyaXNlKCkpCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0jCiMg44OG44O844OW44Or44KS5L+d5a2YCgp0YWJsZV9lZ29fQlAxIDwtIHRhYmxlX2Vnb19CUCAlPiUgbXV0YXRlKGNsdXN0ZXI9ZmFjdG9yKGNsdXN0ZXIsYygiVXAiLCJEb3duIikpKSAlPiUgYXJyYW5nZShjbHVzdGVyLGRlc2MoQ291bnQpKSAjMTkxMTA2CgpyZWFkcjo6d3JpdGVfY3N2KHRhYmxlX2Vnb19CUDEscGFzdGUoZmlsZW5hbWVfY3N2LCIuY3N2IixzZXA9IiIpKQoKIyDlhYjjga7jg4bjg7zjg5bjg6vjga5nZW5lSUTjgpJnZW5lIG5hbWXjgavnva7mj5vjgZnjgovjgIIoMjAxOTEwMjUpCgp0YWJsZWdvIDwtIHRhYmxlX2Vnb19CUDEgJT4lIG11dGF0ZShnZW5lX25hbWU9Z2VuZUlEKSAlPiUgZHBseXI6OnNlbGVjdCgtKHF2YWx1ZSkpCgpmb3IgKGkgaW4gMTpucm93KHRhYmxlX2RlZ2NsdXN0ZXIpKSB7CiAgdGFibGVnbyA8LSB0YWJsZWdvICU+JSBtdXRhdGUoZ2VuZV9uYW1lPWdzdWIoZ2VuZV9uYW1lLCBwYXR0ZXJuPXRhYmxlX2RlZ2NsdXN0ZXIkZW5zX2dlbmVbaV0sIHJlcGxhY2VtZW50PXRhYmxlX2RlZ2NsdXN0ZXIkZXh0X2dlbmVbaV0sIGlnbm9yZS5jYXNlID0gVFJVRSkpCn0KCnByaW50KHRhYmxlZ28pCgpyZWFkcjo6d3JpdGVfY3N2KHRhYmxlZ28scGFzdGUoZmlsZW5hbWVfY3N2LCJfZ2VuZW5hbWUuY3N2IixzZXA9IiIpKQoKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSMKCiNHT+OBrnRlcm3jga7mlbAKcHJpbnQodGFibGVnbyAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIHN1bW1hcmlzZShjb3VudF9HTz1uKCkpKQoKIyMg5aSJ5pu0ICMjCnRhYmxlX2Vnb19CUF8yZ3VuZmRyMHAxX2NsdXN0ZXIgPC0gdGFibGVnbyAjIOiHqueUseOBq+WkieabtOOBmeOCiwoKIy0tLSDjg6Hjg6IgLS0tLSMKI3RhYmxlZ2dnIDwtIHRhYmxlX2Vnb19jbHVzdGVyY2x1c3RlcgojY29sbSA8LSB0YWJsZWdnZyRnZW5lSUQKI2ZvciAoaSBpbiAxOjg4KSB7CiMgIGNvbG0gPC0gc3ViKHJycmVzX2NsdXN0ZXIzJGVuc19nZW5lW2ldLCBycnJlc19jbHVzdGVyMyRleHRfZ2VuZVtpXSwgY29sbSkKI30KI3ByaW50KGNvbG0pCgpgYGAKCmBgYHtyIGNsdXN0ZXJQcm9maWxlICBwYXJ0My00fQojIEJlbmphbWluaSBjb3JyZWN0aW9uIOOCkiBwLWFkanVzdCDjgajjgZfjgabkvb/nlKjjgZnjgosKIyBmaWfjga7jgr/jgqTjg4jjg6vjgpLkv67mraMgKDIwMTkxMjEzKQoKZmlsZV9CUF9wbG90IDwtICIuL2NsdXN0ZXJQcm9maWxlL0JQZmRyMHAxX19Jd2FzYWtpXzAzODZyZV9DMkMxMl9IM21tMThfMmd1bmZkcjBwMV9sb2cyRm9sZENoYW5nZV9maW4yMDA5MTUucGRmIgpmaWxlX0JQX3Bsb3RfbXVzY2xlIDwtICIuL2NsdXN0ZXJQcm9maWxlL0JQZmRyMHAxX19Jd2FzYWtpXzAzODZyZV9DMkMxMl9IM21tMThfMmd1bmZkcjBwMV8yZ3VuZmRyMHAxX2xvZzJGb2xkQ2hhbmdlX211c2NsZW9ubHlfZmluMjAwOTE1LnBkZiIKCgojLS0tLS0tLS0tLS0tLS0tLS0tLS0jCgpCUF9tYXRvbWUgPC0gdGFibGVnbwoKcm93bGVuZ3RoIDwtIEJQX21hdG9tZSAlPiUgZ3JvdXBfYnkoRGVzY3JpcHRpb24pICU+JSBzdW1tYXJpc2UoKSAlPiUgbnJvdygpCkJQX3Bsb3QgPC0gQlBfbWF0b21lICU+JSBmaWx0ZXIocC5hZGp1c3Q8ZmRyKSAlPiUgZ2dwbG90KGFlcyh4PWNsdXN0ZXIsIHk9cmVvcmRlcihEZXNjcmlwdGlvbixDb3VudCksIHNpemU9Q291bnQsIGZpbGw9cC5hZGp1c3QpKSArIGdlb21fcG9pbnQoc2hhcGUgPSAyMSkgKyB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsgdGhlbWVfbWluaW1hbCgpICsgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAicmVkIiAsIGhpZ2ggPSAiYmx1ZSIpKyB4bGFiKCJDMkMxMiAoZmRyIDAuMSkiKSArIHlsYWIoIkdPIERlc2NyaXB0aW9uIChCUCkiKSArIGxhYnMoZmlsbD1wYXN0ZSgicC5hZGp1c3QgKEJIKSA8ICIsYXMuY2hhcmFjdGVyKGZkciksc2VwPSIiKSkKcHJpbnQoQlBfcGxvdCkKZ2dzYXZlKHBsb3Q9QlBfcGxvdCxmaWxlPWZpbGVfQlBfcGxvdCwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gKDUrcm93bGVuZ3RoLzYpLCBkcGkgPSAxMjAsbGltaXRzaXplID0gRkFMU0UpCgojLS0tbXVzY2xl6Zai6YCj44Gu44G/CkJQX21hdG9tZV9tdXNjbGUgPC0gQlBfbWF0b21lICU+JSBmaWx0ZXIoZ3JlcGwoIm11c2NsZSIsIERlc2NyaXB0aW9uKXxncmVwbCgibXlvIiwgRGVzY3JpcHRpb24pKQpyb3dsZW5ndGggPC0gQlBfbWF0b21lX211c2NsZSAlPiUgZ3JvdXBfYnkoRGVzY3JpcHRpb24pICU+JSBzdW1tYXJpc2UoKSAlPiUgbnJvdygpCkJQX3Bsb3RfbXVzY2xlIDwtIEJQX21hdG9tZV9tdXNjbGUgJT4lIGZpbHRlcihwLmFkanVzdDxmZHIpICU+JSBnZ3Bsb3QoYWVzKHg9Y2x1c3RlciwgeT1yZW9yZGVyKERlc2NyaXB0aW9uLENvdW50KSwgc2l6ZT1Db3VudCwgZmlsbD1wLmFkanVzdCkpICsgZ2VvbV9wb2ludChzaGFwZSA9IDIxKSArIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkgKyB0aGVtZV9taW5pbWFsKCkgKyB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKyBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJyZWQiICwgaGlnaCA9ICJibHVlIikgKyB4bGFiKCJDMkMxMiAoZmRyIDAuMSkgKG11c2NsZSkiKSArIHlsYWIoIkdPIERlc2NyaXB0aW9uIChCUCkiKSArIGxhYnMoZmlsbD1wYXN0ZSgicC5hZGp1c3QgKEJIKSA8ICIsYXMuY2hhcmFjdGVyKGZkciksc2VwPSIiKSkKcHJpbnQoQlBfcGxvdF9tdXNjbGUpCmdnc2F2ZShCUF9wbG90X211c2NsZSxmaWxlPWZpbGVfQlBfcGxvdF9tdXNjbGUsIHdpZHRoID0gOCwgaGVpZ2h0ID0gKDUrcm93bGVuZ3RoLzYpLCBkcGkgPSAxMjAsbGltaXRzaXplID0gRkFMU0UpCgoKYGBgCgpgYGB7UiBtZW1vIHBhcnQzLTZ9CgojIHg9cHZhbHVlLCB5PXAuYWRqdXN0CnBsb3R0dCA8LSB0YWJsZV9lZ29fQlAgJT4lIGdncGxvdChhZXMoeD1wdmFsdWUsIHk9cC5hZGp1c3QsIHNpemU9Q291bnQpKSArIGdlb21fcG9pbnQoKStnZW9tX2FibGluZShpbnRlcmNlcHQ9MCxzbG9wZT0xLjAsbGluZXR5cGU9ImRhc2hlZCIsY29sb3VyPSJibHVlIikgKyB4bGltKDAsTkEpICsgeWxpbSgwLE5BKSArIGdndGl0bGUobGFiZWw9cGFzdGUoInAuYWRqdXN0IChCSCkgPCAiLGFzLmNoYXJhY3RlcihmZHIpLHNlcD0iIikpCnByaW50KHBsb3R0dCkKCiMgeD1wdmFsdWUsIHk9cXZhbHVlCnBsb3R0dCA8LSB0YWJsZV9lZ29fQlAgJT4lIGdncGxvdChhZXMoeD1wdmFsdWUsIHk9cXZhbHVlLCBzaXplPUNvdW50KSkgKyBnZW9tX3BvaW50KCkrZ2VvbV9hYmxpbmUoaW50ZXJjZXB0PTAsc2xvcGU9MS4wLGxpbmV0eXBlPSJkYXNoZWQiLGNvbG91cj0iYmx1ZSIpICsgeGxpbSgwLE5BKSArIHlsaW0oMCxOQSkgKyBnZ3RpdGxlKGxhYmVsPXBhc3RlKCJwLmFkanVzdCAoQkgpIDwgIixhcy5jaGFyYWN0ZXIoZmRyKSxzZXA9IiIpKQpwcmludChwbG90dHQpCgojIHg9cC5hZGp1c3QsIHk9cXZhbHVlCnBsb3R0dCA8LSB0YWJsZV9lZ29fQlAgJT4lIGdncGxvdChhZXMoeD1wLmFkanVzdCwgeT1xdmFsdWUsIHNpemU9Q291bnQpKSArIGdlb21fcG9pbnQoKStnZW9tX2FibGluZShpbnRlcmNlcHQ9MCxzbG9wZT0xLjAsbGluZXR5cGU9ImRhc2hlZCIsY29sb3VyPSJibHVlIikgKyB4bGltKDAsTkEpICsgeWxpbSgwLE5BKSArIGdndGl0bGUobGFiZWw9cGFzdGUoInAuYWRqdXN0IChCSCkgPCAiLGFzLmNoYXJhY3RlcihmZHIpLHNlcD0iIikpCnByaW50KHBsb3R0dCkKCgojIyBwdmFsdWUgPCBxdmFsdWUgPCBwLmFkanVzdCAjIwojIHB2YWx1ZSA8IHAuYWRqdXN0CiMgcHZhbHVlIDwgcXZhbHVlCiMgcXZhbHVlIDwgcC5hZGp1c3QKCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0jCgojW0JCUkItc2VxXzA0MzhfUUNfdG1wbF92Nl9ub3VtaV8xOTA1MTUtSDNtbTE4S09fQ1RYX1MyLURheTBfUzNfZmRyMHAydmVyX2FuZF9MUlRfMTkxMDI0ICAodW1p6KOc5q2j44Gq44GXLGZkcjAuMikgKFRQTSAxOTA3MjJ2ZXIpICgxOTA5MjTjgpLlhYPjgaspICgxOTA2MjctMTAyNCld44KS5Y+C6ICD44Gr44GX44Gf44CCCgojcHZhbHVlQ3V0b2ZmCQojcHZhbHVlIGN1dG9mZiBvbiBlbnJpY2htZW50IHRlc3RzIHRvIHJlcG9ydAoKI3BBZGp1c3RNZXRob2QJCiNvbmUgb2YgImhvbG0iLCAiaG9jaGJlcmciLCAiaG9tbWVsIiwgImJvbmZlcnJvbmkiLCAiQkgiLCAiQlkiLCAiZmRyIiwgIm5vbmUiCgojcXZhbHVlQ3V0b2ZmCQojcXZhbHVlIGN1dG9mZiBvbiBlbnJpY2htZW50IHRlc3RzIHRvIHJlcG9ydCBhcyBzaWduaWZpY2FudC4gVGVzdHMgbXVzdCBwYXNzIGkpIHB2YWx1ZUN1dG9mZiBvbiB1bmFkanVzdGVkIHB2YWx1ZXMsIGlpKSBwdmFsdWVDdXRvZmYgb24gYWRqdXN0ZWQgcHZhbHVlcyBhbmQgaWlpKSBxdmFsdWVDdXRvZmYgb24gcXZhbHVlcyB0byBiZSByZXBvcnRlZC4KCiMg6Kit5a6aKHB2YWx1ZUN1dG9mZiAgPSAwLjEsIHF2YWx1ZUN1dG9mZiAgPSAwLjIp44Gg44Go44CBcOWApDwwLjEsIHAuYWRqdXN05YCkPDAuMSwgceWApDwwLjIg44Gr44Gq44Gj44Gm44GE44KL44CCCgpgYGAKCnBsb3QgVG9wIEdPICgyMDIwMDkxNSBhZGQpCgpgYGB7ciBUb3AgR08gZGF0YX0KCnRhYmxlZ29fdG9wIDwtIHRhYmxlZ28gJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSBhcnJhbmdlKGRlc2MoQ291bnQpLCBwLmFkanVzdCwgcHZhbHVlKSAlPiUgbXV0YXRlKHJhbms9cm93X251bWJlcigpKSAlPiUgZmlsdGVyKHJhbms8PTEwKQpwcmludCh0YWJsZWdvX3RvcCkKCmZpbGVuYW1lIDwtIHBhc3RlKGRpcm5hbWUoZmlsZW5hbWVfY3N2KSwiL1RvcDEwX18iLGJhc2VuYW1lKGZpbGVuYW1lX2NzdiksIl9nZW5lbmFtZS5jc3YiLHNlcD0iIikKcHJpbnQoZmlsZW5hbWUpCnJlYWRyOjp3cml0ZV9jc3YodGFibGVnb190b3AsZmlsZW5hbWUpCgojIEMyIFRvcDEwCiNmaWxlX2MyIDwtICIvaG9tZS9ha3V3YWthZG8vbWFrZXBsb3RfMThwcm9qZWN0L0lucHV0ZmlsZS9Jd2FzYWtpXzAzODZyZV9DMkMxMl9IM21tMThfMmd1bmZkcjBwMV9sb2cyRm9sZENoYW5nZV9CUGZkcjBwMV9nZW5lcmF0aW9fVXBEb3duX2dlbmVuYW1lLmNzdiIKI2RhdGFjMiA8LSByZWFkcjo6cmVhZF9jc3YoZmlsZV9jMikgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSBhcnJhbmdlKGRlc2MoQ291bnQpLCBwLmFkanVzdCwgcHZhbHVlKSAlPiUgbXV0YXRlKHJhbms9cm93X251bWJlcigpKSAlPiUgZmlsdGVyKHJhbms8PTEwKQojcHJpbnQoZGF0YWMyKQojZmlsZW5hbWUgPC0gcGFzdGUoIi4vT3V0cHV0ZmlsZS8iLCJUb3AxMF9fIixiYXNlbmFtZShmaWxlX2MyKSxzZXA9IiIpCiNwcmludChmaWxlbmFtZSkKI2RhdGFjMiAlPiUgcmVhZHI6OndyaXRlX2NzdihmaWxlbmFtZSkKCgpgYGAKCuS4gOW6puOBq+aPj+eUuwoKYGBge3IgcGxvdGZhY2V0IGMyLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQoKcGxvdF90YWJsZWdvX3RvcCA8LSB0YWJsZWdvX3RvcCAlPiUgdW5ncm91cCgpICAlPiUgbXV0YXRlKGNsdXN0ZXI9ZmFjdG9yKGNsdXN0ZXIsYygiVXAiLCJEb3duIikpKSAlPiUgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIGRwbHlyOjptdXRhdGUoR2VuZVJhdGlvMT1HZW5lUmF0aW8pICU+JSB0aWR5cjo6c2VwYXJhdGUoY29sPUdlbmVSYXRpbzEsc2VwPSIvIixpbnRvPWMoImNvdW50IiwiQlBfZ2VuZXNpemUiKSkgJT4lIG11dGF0ZShCUF9nZW5lc2l6ZT1hcy5pbnRlZ2VyKEJQX2dlbmVzaXplKSxHZW5lX3JhdGlvPUNvdW50L0JQX2dlbmVzaXplKSAlPiUgZHBseXI6OnNlbGVjdCgtY291bnQpCgpwbG90X3RhYmxlZ29fdG9wICU+JSBzdW1tYXJpc2UobWF4PW1heChHZW5lX3JhdGlvKSxtaW49bWluKEdlbmVfcmF0aW8pKQoKCnBsb3RfdGFibGVnb190b3AgJT4lIHN1bW1hcmlzZShtYXg9bWF4KENvdW50KSxtaW49bWluKENvdW50KSkKCnBsb3RfdGFibGVnb190b3BfMiA8LSBwbG90X3RhYmxlZ29fdG9wICU+JSBtdXRhdGUobmV3X0Rlc2NyaXB0aW9uID0gcGFzdGUoIigiLGNsdXN0ZXIsIikgIixEZXNjcmlwdGlvbixzZXA9IiIpKQoKI3htYXg9MC4xNzUKI3htaW49MC4wODUKI2FsbF9icmVhayA8LSBjKDMsNiw5LDEyLDE1KQoKCnhtYXg9MC4wODUKeG1pbj0wLjA1MAojYWxsX2JyZWFrIDwtIGMoNTUsNjAsNjUsNzAsNzUsODAsODUpCmFsbF9icmVhayA8LSBjKDUwLDU1LDYwLDY1LDcwLDc1KSAjKyBzY2FsZV9zaXplX2FyZWEoYnJlYWtzPWFsbF9icmVhaykKCnNvcnRfcGxvdF90YWJsZWdvX3RvcF8yIDwtIHBsb3RfdGFibGVnb190b3BfMiAlPiUgYXJyYW5nZShkZXNjKHJhbmspKQoKZ2dnVSA8LSBwbG90X3RhYmxlZ29fdG9wXzIgJT4lIGFycmFuZ2UoZGVzYyhyYW5rKSkgJT4lIG11dGF0ZShuZXdfRGVzY3JpcHRpb24gPWZhY3RvcihuZXdfRGVzY3JpcHRpb24sc29ydF9wbG90X3RhYmxlZ29fdG9wXzIkbmV3X0Rlc2NyaXB0aW9uKSkgJT4lIGdncGxvdChhZXMoeD1HZW5lX3JhdGlvLCB5PW5ld19EZXNjcmlwdGlvbiwgZmlsbD1wLmFkanVzdCkpICsgZ2VvbV9wb2ludChhZXMoc2l6ZT1Db3VudCksc2hhcGUgPSAyMSkgKyB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IixsZWdlbmQuYm94PSJob3Jpem9udGFsIixzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQodmp1c3QgPSAxKSxzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gInJlZCIgLCBoaWdoID0gImJsdWUiLGxpbWl0cyA9IGMoMCwgMC4xKSkgKyB4bGltKHhtaW4seG1heCkgKyBmYWNldF93cmFwKH5jbHVzdGVyLHNjYWxlcyA9ICJmcmVlX3kiLG5jb2w9MSkKCmdnZ1UwIDwtIHBsb3RfdGFibGVnb190b3BfMiAlPiUgYXJyYW5nZShkZXNjKHJhbmspKSAlPiUgbXV0YXRlKG5ld19EZXNjcmlwdGlvbiA9ZmFjdG9yKG5ld19EZXNjcmlwdGlvbixzb3J0X3Bsb3RfdGFibGVnb190b3BfMiRuZXdfRGVzY3JpcHRpb24pKSAgJT4lIGdncGxvdChhZXMoeD1HZW5lX3JhdGlvLCB5PW5ld19EZXNjcmlwdGlvbiwgZmlsbD1wLmFkanVzdCkpICsgZ2VvbV9wb2ludChhZXMoc2l6ZT1Db3VudCksc2hhcGUgPSAyMSkgKyB0aGVtZV9idygpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IixsZWdlbmQuYm94PSJob3Jpem9udGFsIixzdHJpcC50ZXh0ID0gZWxlbWVudF9ibGFuaygpLGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGxlZ2VuZC50ZXh0ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSxzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gInJlZCIgLCBoaWdoID0gImJsdWUiLGxpbWl0cyA9IGMoMCwgMC4xKSkgKyB4bGltKHhtaW4seG1heCkgKyBmYWNldF93cmFwKH5jbHVzdGVyLHNjYWxlcyA9ICJmcmVlX3kiLG5jb2w9MSkKCnByaW50KGdnZ1UpCnByaW50KGdnZ1UwKQoKZmlsZW5hbWUgPC0gcGFzdGUoZGlybmFtZShmaWxlbmFtZV9jc3YpLCIvVG9wMTBfXyIsYmFzZW5hbWUoZmlsZW5hbWVfY3N2KSwiX3Bsb3QucGRmIixzZXA9IiIpCnByaW50KGZpbGVuYW1lKQpnZ3NhdmUoZ2dnVSxmaWxlPWZpbGVuYW1lLCB3aWR0aCA9IDgsIGhlaWdodCA9IDcsIGRwaSA9IDEyMCxsaW1pdHNpemUgPSBGQUxTRSkKCmZpbGVuYW1lIDwtIHBhc3RlKGRpcm5hbWUoZmlsZW5hbWVfY3N2KSwiL1RvcDEwX18iLGJhc2VuYW1lKGZpbGVuYW1lX2NzdiksIl9wbG90X25vbmUucGRmIixzZXA9IiIpCnByaW50KGZpbGVuYW1lKQpnZ3NhdmUoZ2dnVTAsZmlsZT1maWxlbmFtZSwgd2lkdGggPSA0LCBoZWlnaHQgPSA3LCBkcGkgPSAxMjAsbGltaXRzaXplID0gRkFMU0UpCgoKI2dnc2F2ZShnZ2dVLGZpbGU9cGFzdGUoIi4vT3V0cHV0ZmlsZS8iLCJDMkMxMl9IM21tMThfQ0VMMDM4NnJlX19jbHVzdGVyQWxsX1RvcDEwX0JQZmRyMHAxX3Bsb3QucGRmIixzZXA9IiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDcsIGRwaSA9IDEyMCxsaW1pdHNpemUgPSBGQUxTRSkKI2dnc2F2ZShnZ2dVMCxmaWxlPXBhc3RlKCIuL091dHB1dGZpbGUvIiwiQzJDMTJfSDNtbTE4X0NFTDAzODZyZV9fY2x1c3RlckFsbF9Ub3AxMF9CUGZkcjBwMV9wbG90X25vbmUucGRmIixzZXA9IiIpLCB3aWR0aCA9IDQsIGhlaWdodCA9IDcsIGRwaSA9IDEyMCxsaW1pdHNpemUgPSBGQUxTRSkKCgpgYGAKCgpUb3AgR08gdGVybSBoZWF0bWFwCgooR08gMjAyMDA5MTV2ZXIpCgoKYGBge3IgbG9hZCBkYXRhIEdPfQoKR09kYXRhX3RvcDEwIDwtIHRhYmxlZ29fdG9wCgpyYWEgPC0gc3Ryc3BsaXQoR09kYXRhX3RvcDEwJGdlbmVJRCAsICIvIikKCmZvciAoaSBpbiAxOm5yb3coR09kYXRhX3RvcDEwKSkgewogIHJiYmIgPC0gZGF0YS5mcmFtZShEZXNjcmlwdGlvbj1yZXAoR09kYXRhX3RvcDEwJERlc2NyaXB0aW9uW2ldLGxlbmd0aChyYWFbW2ldXSkpLCBjbHVzdGVyPXJlcChHT2RhdGFfdG9wMTAkY2x1c3RlcltpXSxsZW5ndGgocmFhW1tpXV0pKSwgZW5zX2dlbmU9cmFhW1tpXV0pCgogIGlmIChpID09IDEpIHsKICAgIFRvcDEwR08gPC0gcmJiYgogIH0gCiAgZWxzZSB7CiAgICAgVG9wMTBHTyA8LSBUb3AxMEdPICU+JSBiaW5kX3Jvd3MocmJiYikKICB9Cn0KClRvcDEwR09fdCA8LSBUb3AxMEdPICU+JSBhc190aWJibGUoKSAlPiUgbXV0YXRlKERlc2NyaXB0aW9uPWFzLmNoYXJhY3RlcihEZXNjcmlwdGlvbiksZW5zX2dlbmU9YXMuY2hhcmFjdGVyKGVuc19nZW5lKSxjbHVzdGVyPWFzLmNoYXJhY3RlcihjbHVzdGVyKSkKClRvcDEwR09fcyA8LSBUb3AxMEdPX3QgJT4lIGdyb3VwX2J5KGVuc19nZW5lLGNsdXN0ZXIpICU+JSBzdW1tYXJpc2UoRGVzPXBhc3RlKERlc2NyaXB0aW9uLCBjb2xsYXBzZSA9ICIsICIpKSAlPiUgdW5ncm91cCgpCgpyZWFkcjo6d3JpdGVfY3N2KFRvcDEwR09fcywgIi4vY2x1c3RlclByb2ZpbGUvaGVhdG1hcC9DRUwwMzg2bm91bWlfQzJDMTJfSDNtbTE4X19ERUdfR090b3AxMF9nZW5lbGlzdF9fMjAyMDA5MTUuY3N2IikKClRvcDEwR09fc19kb3duIDwtIFRvcDEwR09fcyAlPiUgZmlsdGVyKGNsdXN0ZXI9PSJEb3duIikKVG9wMTBHT19zX3VwIDwtIFRvcDEwR09fcyAlPiUgZmlsdGVyKGNsdXN0ZXI9PSJVcCIpICAKCmBgYAoKCmBgYHtyIGhlYXRtYXB9Cgp6c2NvcmVfdHlwZV9Ub3AxMEdPX2RlZyA8LSB6c2NvcmVfdHlwZSAlPiUgZmlsdGVyKGVuc19nZW5lICVpbiUgVG9wMTBHT19zJGVuc19nZW5lKQoKenNjb3JlX3R5cGVfVG9wMTBHT191cCA8LSB6c2NvcmVfdHlwZSAlPiUgZmlsdGVyKGVuc19nZW5lICVpbiUgVG9wMTBHT19zX3VwJGVuc19nZW5lKQp6c2NvcmVfdHlwZV9Ub3AxMEdPX2Rvd24gPC0genNjb3JlX3R5cGUgJT4lIGZpbHRlcihlbnNfZ2VuZSAlaW4lIFRvcDEwR09fc19kb3duJGVuc19nZW5lKQoKenNjb3JlX3R5cGVfaG91c2VrZWVwIDwtIHpzY29yZV90eXBlICU+JSBmaWx0ZXIoZXh0X2dlbmUgJWluJSBjKCJScGwyNyIsIkFjdGIiLCJHYXBkaCIpKQpyZSAlPiUgZmlsdGVyKGV4dF9nZW5lICVpbiUgYygiUnBsMjciLCJBY3RiIiwiR2FwZGgiKSkKCmBgYAoKIyMjIHogc2NvcmUgaGVhdG1hcCAobmV3KQoKYGBge3IgaGVhdG1hcCBjbHVzdGVyaW5nIGRyYXcsIGZpZy5oaWdodD0xMCxmaWcud2lkdGg9MTB9CgpicmVha3NMaXN0ID0gc2VxKC0zLjAsIDMuMCwgMC4xKQpoZWF0bWFwY29scyA8LSBjb2xvclJhbXBQYWxldHRlKHJldihicmV3ZXIucGFsKG49NyxuYW1lPSJSZFlsQnUiKSkpKGxlbmd0aChicmVha3NMaXN0KSkKCmRlZl9zZWxlY3QgPC0gZGVmICU+JSBkcGx5cjo6ZmlsdGVyKGdyb3VwICVpbiUgYygibW0xOEJfRyIsICJlR0ZQX0ciLCJtbTE4Ql9ENzIiLCAiZUdGUF9ENzIiKSkgJT4lIG11dGF0ZShncm91cD1mYWN0b3IoZ3JvdXAsYygiZUdGUF9HIiwibW0xOEJfRyIsImVHRlBfRDcyIiwgIm1tMThCX0Q3MiIpKSkgJT4lIGFycmFuZ2UoZ3JvdXAsc2FtcGxlKQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09IwoKCiNhbm5vX3JvdyA8LSBkYXRhLmZyYW1lKENociA9IHpzY29yZV9CUkJERUckY2hyLCBjbHVzdGVyID0genNjb3JlX0JSQkRFRyRjbHVzdGVyKQojcm93bmFtZXMoYW5ub19yb3cpIDwtIHpzY29yZV9CUkJERUckZXh0X2dlbmUKCiNhbm5vX2NvbCA8LSBkYXRhLmZyYW1lKFNlcSA9IGRlZl9saXN0X3NlbGVjdCRzZXEsIERveCA9IGRlZl9saXN0X3NlbGVjdCR0eXBlKQojcm93bmFtZXMoYW5ub19jb2wpIDwtIGRlZl9saXN0X3NlbGVjdCRzYW1wbGUKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSMKCgp6c2NvcmVfbWF0X2Rvd24gPC0gIHpzY29yZV90eXBlX1RvcDEwR09fZG93biAlPiUgZHBseXI6OnNlbGVjdChhbGxfb2YoZGVmX3NlbGVjdCRzYW1wbGUpKSAlPiUgYXMubWF0cml4KCkKcm93bmFtZXMoenNjb3JlX21hdF9kb3duKSA8LSB6c2NvcmVfdHlwZV9Ub3AxMEdPX2Rvd24kZXh0X2dlbmUKaGVhdF90aXRsZV9kb3duIDwtIHBhc3RlKCJUb3AxMEdPIGRvd246ICIsbnJvdyh6c2NvcmVfdHlwZV9Ub3AxMEdPX2Rvd24pLCIgVG90YWw6ICIsbnJvdyh6c2NvcmVfdHlwZSksc2VwPSIiKQoKenNjb3JlX21hdF91cCA8LSAgenNjb3JlX3R5cGVfVG9wMTBHT191cCAlPiUgZHBseXI6OnNlbGVjdChhbGxfb2YoZGVmX3NlbGVjdCRzYW1wbGUpKSAlPiUgYXMubWF0cml4KCkKcm93bmFtZXMoenNjb3JlX21hdF91cCkgPC0genNjb3JlX3R5cGVfVG9wMTBHT191cCRleHRfZ2VuZQpoZWF0X3RpdGxlX3VwIDwtIHBhc3RlKCJUb3AxMEdPIHVwOiAiLG5yb3coenNjb3JlX3R5cGVfVG9wMTBHT191cCksIiBUb3RhbDogIixucm93KHpzY29yZV90eXBlKSxzZXA9IiIpCgp6c2NvcmVfbWF0X2tlZXAgPC0gIHpzY29yZV90eXBlX2hvdXNla2VlcCAlPiUgZHBseXI6OnNlbGVjdChhbGxfb2YoZGVmX3NlbGVjdCRzYW1wbGUpKSAlPiUgYXMubWF0cml4KCkKcm93bmFtZXMoenNjb3JlX21hdF9rZWVwKSA8LSB6c2NvcmVfdHlwZV9ob3VzZWtlZXAkZXh0X2dlbmUKaGVhdF90aXRsZV9rZWVwIDwtIHBhc3RlKCJIb3VzZWtlZXBpbmc6ICIsbnJvdyh6c2NvcmVfdHlwZV9ob3VzZWtlZXApLCIgVG90YWw6ICIsbnJvdyh6c2NvcmVfdHlwZSksc2VwPSIiKQoKCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0jCnpfaGVhdDEgPC0gcGhlYXRtYXA6OnBoZWF0bWFwKHpzY29yZV9tYXRfZG93biwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgIG1haW4gPSBoZWF0X3RpdGxlX2Rvd24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICBzY2FsZSA9ICJub25lIiwKICAgICAKICAgICAjY2x1c3Rlcl9yb3dzID0gRkFMU0UsICNwZWFrIChjbHVzdGVy44GnKSAgKOmgmOWfn+WQjSkKICAgICAjY2x1c3Rlcl9jb2xzID0gRkFMU0UsICNzYW1wbHJmCiAgICAgI2NsdXN0ZXJfcm93cyA9IEZBTFNFLCAjcGVhayAoY2x1c3RlcuOBpykgICjpoJjln5/lkI0pCiAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwgI3BlYWsgKGNsdXN0ZXLjgacpICAo6aCY5Z+f5ZCNKQogICAgIGNsdXN0ZXJfY29scyA9IEZBTFNFLCAjc2FtcGxyZgoKICAgICAjc2hvd19yb3duYW1lcyA9IFRSVUUsICNwZWFr5ZCNICjpoJjln5/lkI0pCiAgICAgc2hvd19yb3duYW1lcyA9IFRSVUUsICNwZWFr5ZCNICjpoJjln5/lkI0pCiAgICAgc2hvd19jb2xuYW1lcyA9IFRSVUUsICNzYW1wbGVfcG9zaXRpb27lkI0gKOODouODgeODvOODleWQjSkKICAgICAKICAgICAjYW5ub3RhdGlvbl9uYW1lc19jb2wgPSBUUlVFLAogICAgICNzaG93X3Jvd25hbWVzID0gVFJVRSwgI3BlYWvlkI0KICAgICAjc2hvd19jb2xuYW1lcyA9IFRSVUUsICNzYW1wbGVfcG9zaXRpb27lkI0KICAgICAjYW5ub3RhdGlvbl9uYW1lc19jb2wgPVRSVUUsCiAgICAgI2dhcHNfcm93PXRhYmxlX2dhcCRub25vbywKICAgICAjZ2Fwc19jb2w9YygzLDYsOCwxMSksCiAgICAgCiAgICAgI25hX2NvbCA9IndoaXRlIiwKCiAgICAgZ2Fwc19yb3c9Yyg4MCksCiAgICAgZ2Fwc19jb2w9IHNlcSg1LCAyMCwgNSksCiAgICAgI2dhcHNfY29sPSBzZXEoMiwgOCoyLCAyKSwKICAgICAjZ2Fwc19jb2w9IGMoMiw0LDYsOCwxMCwxMiwxNCksICMgYygzLCA2LCA5LCAxMiksICNnYXBzX2NvbD0gc2VxKDIsIDYqMiwgMiksCiAgICAgI2dhcHNfY29sPWMoMjAwLDQwMCw2MDAsODAwLDEwMDAsMTIwMCwxNDAwLDE2MDAsMTgwMCwyMDAwLDIyMDAsMjQwMCksIGdhcHNfY29sPSBzZXEoMjAwLCAxMioyMDAsIDIwMCksCiAgICAgI2NlbGxoZWlnaHQgPSBucm93KG15bWF0cml4Ml8xKSooMC4yNSksCiAgICAgI2NlbGx3aWR0aCA9IDIwLAogICAgICNjZWxsaGVpZ2h0ID0gNDAwL25yb3cobXltYXRyaXgxKSwKICAgICAjY2VsbGhlaWdodCA9IDAuMDA1LCAgICNjZWxsaGVpZ2h0ID0gMS41LAogICAgICNjZWxsaGVpZ2h0ID0gMC4wMTAsICAgI2NlbGxoZWlnaHQgPSAxLjUsCiAgICAgY2VsbGhlaWdodCA9IDQuMCwgICAjY2VsbGhlaWdodCA9IDEuNSwKICAgICBjZWxsd2lkdGggPSA0MCwgICAgICAjY2VsbHdpZHRoID0gMywKICAgICAjY2VsbGhlaWdodCA9IDAuNywgICAjY2VsbGhlaWdodCA9IDEuNSwKICAgICAjY2VsbHdpZHRoID0gOCwgICAgICAjY2VsbHdpZHRoID0gMywKICAgICAjY2VsbGhlaWdodCA9IDYsICAgI2NlbGxoZWlnaHQgPSAxLjUsCgogICAgICNjZWxsaGVpZ2h0ID0gNiwgICAjY2VsbGhlaWdodCA9IDEuNSwKICAgICAjY2VsbHdpZHRoID0gNywgICAgICAjY2VsbHdpZHRoID0gMywKICAgICAjY2VsbGhlaWdodCA9IDAuNywgICAjY2VsbGhlaWdodCA9IDEuNSwKICAgICAjY2VsbHdpZHRoID0gMTUsICAgICAgI2NlbGx3aWR0aCA9IDMsCiAgICAgI2JvcmRlcl9jb2xvcj0iZ3JheSIsICAjYm9yZGVyX2NvbG9yPSIjMDAwMDAwIiwKICAgICBib3JkZXJfY29sb3I9TkEsCiAgICAgI2ZvbnRzaXplX3JvdyA9IDYsCiAgICAgI2Fubm90YXRpb25fcm93ID0gbWl4ZWRfbmFtZSwKICAgICAjYW5ub3RhdGlvbl9yb3cgPSBhbm5vX3JvdywKICAgICAjYW5ub3RhdGlvbl9jb2wgPSBhbm5vX2NvbCwKICAgICAKIyAgICAgY3V0cmVlX3Jvd3MgPSA2LAogICAgICNjdXRyZWVfcm93cyA9IDEwLAogICAgIAogICAgICNkaXNwbGF5X251bWJlcnMgPSBUUlVFLAogICAgICNudW1iZXJfZm9ybWF0ID0gIiUxLjJlIiwKICAgICAjbnVtYmVyX2NvbG9yID0gImJsYWNrIiwKICAgICAjYW5ub3RhdGlvbl9jb2wgPSBhbm5vdGRmX3NhbXBsZQogICAgIGZvbnRzaXplX2NvbCA9IDUsCiAgICAgZm9udHNpemVfcm93ID0gMy43LAogICAgICNmb250c2l6ZV9yb3cgPSAwLjYsCiAgICAgbGVnZW5kPVRSVUUsCiAgICAgI2xlZ2VuZF9icmVha3MgPSBsZWdfYnJlYWssCiAgICAgI2xlZ2VuZF9sYWJlbHMgPSBhcy5jaGFyYWN0ZXIobGVnX2JyZWFrKSwKICAgICBicmVha3MgPSBicmVha3NMaXN0LAogICAgIGNvbG9yID0gaGVhdG1hcGNvbHMKICAgICAjYW5ub3RhdGlvbl9jb2xvcnMgPSBteWNvbG9ycwogICAgICN0cmVlaGVpZ2h0X3JvdyA9IDEwCikKCmdnc2F2ZShwbG90PXpfaGVhdDEsZmlsZT0iLi9jbHVzdGVyUHJvZmlsZS9oZWF0bWFwL2hlYXRtYXBfZG93bi5wZGYiLCB3aWR0aCA9IDE1LCBoZWlnaHQgPSAxNSwgZHBpID0gMzYwLCBsaW1pdHNpemUgPSBGQUxTRSkKCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0jCnpfaGVhdDEgPC0gcGhlYXRtYXA6OnBoZWF0bWFwKHpzY29yZV9tYXRfdXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICBtYWluID0gaGVhdF90aXRsZV91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgc2NhbGUgPSAibm9uZSIsCiAgICAgCiAgICAgI2NsdXN0ZXJfcm93cyA9IEZBTFNFLCAjcGVhayAoY2x1c3RlcuOBpykgICjpoJjln5/lkI0pCiAgICAgI2NsdXN0ZXJfY29scyA9IEZBTFNFLCAjc2FtcGxyZgogICAgICNjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgI3BlYWsgKGNsdXN0ZXLjgacpICAo6aCY5Z+f5ZCNKQogICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsICNwZWFrIChjbHVzdGVy44GnKSAgKOmgmOWfn+WQjSkKICAgICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgI3NhbXBscmYKCiAgICAgI3Nob3dfcm93bmFtZXMgPSBUUlVFLCAjcGVha+WQjSAo6aCY5Z+f5ZCNKQogICAgIHNob3dfcm93bmFtZXMgPSBUUlVFLCAjcGVha+WQjSAo6aCY5Z+f5ZCNKQogICAgIHNob3dfY29sbmFtZXMgPSBUUlVFLCAjc2FtcGxlX3Bvc2l0aW9u5ZCNICjjg6Ljg4Hjg7zjg5XlkI0pCiAgICAgCiAgICAgI2Fubm90YXRpb25fbmFtZXNfY29sID0gVFJVRSwKICAgICAjc2hvd19yb3duYW1lcyA9IFRSVUUsICNwZWFr5ZCNCiAgICAgI3Nob3dfY29sbmFtZXMgPSBUUlVFLCAjc2FtcGxlX3Bvc2l0aW9u5ZCNCiAgICAgI2Fubm90YXRpb25fbmFtZXNfY29sID1UUlVFLAogICAgICNnYXBzX3Jvdz10YWJsZV9nYXAkbm9ub28sCiAgICAgI2dhcHNfY29sPWMoMyw2LDgsMTEpLAogICAgIAogICAgICNuYV9jb2wgPSJ3aGl0ZSIsCgogICAgIGdhcHNfcm93PWMoODApLAogICAgIGdhcHNfY29sPSBzZXEoNSwgMjAsIDUpLAogICAgICNnYXBzX2NvbD0gc2VxKDIsIDgqMiwgMiksCiAgICAgI2dhcHNfY29sPSBjKDIsNCw2LDgsMTAsMTIsMTQpLCAjIGMoMywgNiwgOSwgMTIpLCAjZ2Fwc19jb2w9IHNlcSgyLCA2KjIsIDIpLAogICAgICNnYXBzX2NvbD1jKDIwMCw0MDAsNjAwLDgwMCwxMDAwLDEyMDAsMTQwMCwxNjAwLDE4MDAsMjAwMCwyMjAwLDI0MDApLCBnYXBzX2NvbD0gc2VxKDIwMCwgMTIqMjAwLCAyMDApLAogICAgICNjZWxsaGVpZ2h0ID0gbnJvdyhteW1hdHJpeDJfMSkqKDAuMjUpLAogICAgICNjZWxsd2lkdGggPSAyMCwKICAgICAjY2VsbGhlaWdodCA9IDQwMC9ucm93KG15bWF0cml4MSksCiAgICAgI2NlbGxoZWlnaHQgPSAwLjAwNSwgICAjY2VsbGhlaWdodCA9IDEuNSwKICAgICAjY2VsbGhlaWdodCA9IDAuMDEwLCAgICNjZWxsaGVpZ2h0ID0gMS41LAogICAgIGNlbGxoZWlnaHQgPSA0LjAsICAgI2NlbGxoZWlnaHQgPSAxLjUsCiAgICAgY2VsbHdpZHRoID0gNDAsICAgICAgI2NlbGx3aWR0aCA9IDMsCiAgICAgI2NlbGxoZWlnaHQgPSAwLjcsICAgI2NlbGxoZWlnaHQgPSAxLjUsCiAgICAgI2NlbGx3aWR0aCA9IDgsICAgICAgI2NlbGx3aWR0aCA9IDMsCiAgICAgI2NlbGxoZWlnaHQgPSA2LCAgICNjZWxsaGVpZ2h0ID0gMS41LAoKICAgICAjY2VsbGhlaWdodCA9IDYsICAgI2NlbGxoZWlnaHQgPSAxLjUsCiAgICAgI2NlbGx3aWR0aCA9IDcsICAgICAgI2NlbGx3aWR0aCA9IDMsCiAgICAgI2NlbGxoZWlnaHQgPSAwLjcsICAgI2NlbGxoZWlnaHQgPSAxLjUsCiAgICAgI2NlbGx3aWR0aCA9IDE1LCAgICAgICNjZWxsd2lkdGggPSAzLAogICAgICNib3JkZXJfY29sb3I9ImdyYXkiLCAgI2JvcmRlcl9jb2xvcj0iIzAwMDAwMCIsCiAgICAgYm9yZGVyX2NvbG9yPU5BLAogICAgICNmb250c2l6ZV9yb3cgPSA2LAogICAgICNhbm5vdGF0aW9uX3JvdyA9IG1peGVkX25hbWUsCiAgICAgI2Fubm90YXRpb25fcm93ID0gYW5ub19yb3csCiAgICAgI2Fubm90YXRpb25fY29sID0gYW5ub19jb2wsCiAgICAgCiMgICAgIGN1dHJlZV9yb3dzID0gNiwKICAgICAjY3V0cmVlX3Jvd3MgPSAxMCwKICAgICAKICAgICAjZGlzcGxheV9udW1iZXJzID0gVFJVRSwKICAgICAjbnVtYmVyX2Zvcm1hdCA9ICIlMS4yZSIsCiAgICAgI251bWJlcl9jb2xvciA9ICJibGFjayIsCiAgICAgI2Fubm90YXRpb25fY29sID0gYW5ub3RkZl9zYW1wbGUKICAgICBmb250c2l6ZV9jb2wgPSA1LAogICAgIGZvbnRzaXplX3JvdyA9IDMuNywKICAgICAjZm9udHNpemVfcm93ID0gMC42LAogICAgIGxlZ2VuZD1UUlVFLAogICAgICNsZWdlbmRfYnJlYWtzID0gbGVnX2JyZWFrLAogICAgICNsZWdlbmRfbGFiZWxzID0gYXMuY2hhcmFjdGVyKGxlZ19icmVhayksCiAgICAgYnJlYWtzID0gYnJlYWtzTGlzdCwKICAgICBjb2xvciA9IGhlYXRtYXBjb2xzCiAgICAgI2Fubm90YXRpb25fY29sb3JzID0gbXljb2xvcnMKICAgICAjdHJlZWhlaWdodF9yb3cgPSAxMAopCgojZ2dzYXZlKHBsb3Q9el9oZWF0MSxmaWxlPSIuL0gzSzI3bWUzX0NoSUxfaGVhdG1hcC5wbmciLCB3aWR0aCA9IDgsIGhlaWdodCA9IDE1LCBkcGkgPSAzNjAsIGxpbWl0c2l6ZSA9IEZBTFNFKQpnZ3NhdmUocGxvdD16X2hlYXQxLGZpbGU9Ii4vY2x1c3RlclByb2ZpbGUvaGVhdG1hcC9oZWF0bWFwX3VwLnBkZiIsIHdpZHRoID0gMTUsIGhlaWdodCA9IDIwLCBkcGkgPSAzNjAsIGxpbWl0c2l6ZSA9IEZBTFNFKQoKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSMKel9oZWF0MSA8LSBwaGVhdG1hcDo6cGhlYXRtYXAoenNjb3JlX21hdF9rZWVwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgbWFpbiA9IGhlYXRfdGl0bGVfa2VlcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgIHNjYWxlID0gIm5vbmUiLAogICAgIAogICAgIAogICAgICNjbHVzdGVyX3Jvd3MgPSBGQUxTRSwgI3BlYWsgKGNsdXN0ZXLjgacpICAo6aCY5Z+f5ZCNKQogICAgICNjbHVzdGVyX2NvbHMgPSBGQUxTRSwgI3NhbXBscmYKICAgICAjY2x1c3Rlcl9yb3dzID0gRkFMU0UsICNwZWFrIChjbHVzdGVy44GnKSAgKOmgmOWfn+WQjSkKICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLCAjcGVhayAoY2x1c3RlcuOBpykgICjpoJjln5/lkI0pCiAgICAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsICNzYW1wbHJmCgogICAgICNzaG93X3Jvd25hbWVzID0gVFJVRSwgI3BlYWvlkI0gKOmgmOWfn+WQjSkKICAgICBzaG93X3Jvd25hbWVzID0gVFJVRSwgI3BlYWvlkI0gKOmgmOWfn+WQjSkKICAgICBzaG93X2NvbG5hbWVzID0gVFJVRSwgI3NhbXBsZV9wb3NpdGlvbuWQjSAo44Oi44OB44O844OV5ZCNKQogICAgIAogICAgICNhbm5vdGF0aW9uX25hbWVzX2NvbCA9IFRSVUUsCiAgICAgI3Nob3dfcm93bmFtZXMgPSBUUlVFLCAjcGVha+WQjQogICAgICNzaG93X2NvbG5hbWVzID0gVFJVRSwgI3NhbXBsZV9wb3NpdGlvbuWQjQogICAgICNhbm5vdGF0aW9uX25hbWVzX2NvbCA9VFJVRSwKICAgICAjZ2Fwc19yb3c9dGFibGVfZ2FwJG5vbm9vLAogICAgICNnYXBzX2NvbD1jKDMsNiw4LDExKSwKICAgICAKICAgICAjbmFfY29sID0id2hpdGUiLAoKICAgICBnYXBzX3Jvdz1jKDgwKSwKICAgICBnYXBzX2NvbD0gc2VxKDUsIDIwLCA1KSwKICAgICAjZ2Fwc19jb2w9IHNlcSgyLCA4KjIsIDIpLAogICAgICNnYXBzX2NvbD0gYygyLDQsNiw4LDEwLDEyLDE0KSwgIyBjKDMsIDYsIDksIDEyKSwgI2dhcHNfY29sPSBzZXEoMiwgNioyLCAyKSwKICAgICAjZ2Fwc19jb2w9YygyMDAsNDAwLDYwMCw4MDAsMTAwMCwxMjAwLDE0MDAsMTYwMCwxODAwLDIwMDAsMjIwMCwyNDAwKSwgZ2Fwc19jb2w9IHNlcSgyMDAsIDEyKjIwMCwgMjAwKSwKICAgICAjY2VsbGhlaWdodCA9IG5yb3cobXltYXRyaXgyXzEpKigwLjI1KSwKICAgICAjY2VsbHdpZHRoID0gMjAsCiAgICAgI2NlbGxoZWlnaHQgPSA0MDAvbnJvdyhteW1hdHJpeDEpLAogICAgICNjZWxsaGVpZ2h0ID0gMC4wMDUsICAgI2NlbGxoZWlnaHQgPSAxLjUsCiAgICAgI2NlbGxoZWlnaHQgPSAwLjAxMCwgICAjY2VsbGhlaWdodCA9IDEuNSwKICAgICBjZWxsaGVpZ2h0ID0gNC4wLCAgICNjZWxsaGVpZ2h0ID0gMS41LAogICAgIGNlbGx3aWR0aCA9IDQwLCAgICAgICNjZWxsd2lkdGggPSAzLAogICAgICNjZWxsaGVpZ2h0ID0gMC43LCAgICNjZWxsaGVpZ2h0ID0gMS41LAogICAgICNjZWxsd2lkdGggPSA4LCAgICAgICNjZWxsd2lkdGggPSAzLAogICAgICNjZWxsaGVpZ2h0ID0gNiwgICAjY2VsbGhlaWdodCA9IDEuNSwKCiAgICAgI2NlbGxoZWlnaHQgPSA2LCAgICNjZWxsaGVpZ2h0ID0gMS41LAogICAgICNjZWxsd2lkdGggPSA3LCAgICAgICNjZWxsd2lkdGggPSAzLAogICAgICNjZWxsaGVpZ2h0ID0gMC43LCAgICNjZWxsaGVpZ2h0ID0gMS41LAogICAgICNjZWxsd2lkdGggPSAxNSwgICAgICAjY2VsbHdpZHRoID0gMywKICAgICAjYm9yZGVyX2NvbG9yPSJncmF5IiwgICNib3JkZXJfY29sb3I9IiMwMDAwMDAiLAogICAgIGJvcmRlcl9jb2xvcj1OQSwKICAgICAjZm9udHNpemVfcm93ID0gNiwKICAgICAjYW5ub3RhdGlvbl9yb3cgPSBtaXhlZF9uYW1lLAogICAgICNhbm5vdGF0aW9uX3JvdyA9IGFubm9fcm93LAogICAgICNhbm5vdGF0aW9uX2NvbCA9IGFubm9fY29sLAogICAgIAojICAgICBjdXRyZWVfcm93cyA9IDYsCiAgICAgI2N1dHJlZV9yb3dzID0gMTAsCiAgICAgCiAgICAgI2Rpc3BsYXlfbnVtYmVycyA9IFRSVUUsCiAgICAgI251bWJlcl9mb3JtYXQgPSAiJTEuMmUiLAogICAgICNudW1iZXJfY29sb3IgPSAiYmxhY2siLAogICAgICNhbm5vdGF0aW9uX2NvbCA9IGFubm90ZGZfc2FtcGxlCiAgICAgZm9udHNpemVfY29sID0gNSwKICAgICBmb250c2l6ZV9yb3cgPSAzLjcsCiAgICAgI2ZvbnRzaXplX3JvdyA9IDAuNiwKICAgICBsZWdlbmQ9VFJVRSwKICAgICAjbGVnZW5kX2JyZWFrcyA9IGxlZ19icmVhaywKICAgICAjbGVnZW5kX2xhYmVscyA9IGFzLmNoYXJhY3RlcihsZWdfYnJlYWspLAogICAgIGJyZWFrcyA9IGJyZWFrc0xpc3QsCiAgICAgY29sb3IgPSBoZWF0bWFwY29scwogICAgICNhbm5vdGF0aW9uX2NvbG9ycyA9IG15Y29sb3JzCiAgICAgI3RyZWVoZWlnaHRfcm93ID0gMTAKKQoKI2dnc2F2ZShwbG90PXpfaGVhdDEsZmlsZT0iLi9IM0syN21lM19DaElMX2hlYXRtYXAucG5nIiwgd2lkdGggPSA4LCBoZWlnaHQgPSAxNSwgZHBpID0gMzYwLCBsaW1pdHNpemUgPSBGQUxTRSkKZ2dzYXZlKHBsb3Q9el9oZWF0MSxmaWxlPSIuL2NsdXN0ZXJQcm9maWxlL2hlYXRtYXAvaGVhdG1hcF9ob3VzZWtlZXBpbmcucGRmIiwgd2lkdGggPSAxNSwgaGVpZ2h0ID0gMTUsIGRwaSA9IDM2MCwgbGltaXRzaXplID0gRkFMU0UpCgpgYGAKCgoKIyMjIG5vcm1hbGl6ZWQgY291bnQgcGxvdAoKYGBge3Igbm9ybUNvdW50IE1hdG9tZX0KIyAyMDE5IDEy5pyI5L2c5oiQCgpub3JtX3Bsb3RsaXN0X2FsbF9uYW1lIDwtIG5vcm1fcGxvdGxpc3RfYWxsICU+JSBpbm5lcl9qb2luKGUyZywgYnkgPSAiZW5zX2dlbmUiKSAKcmVhZHI6OndyaXRlX2Nzdihub3JtX3Bsb3RsaXN0X2FsbF9uYW1lLCJOb3JtX2RlZnRhYmxlX2FsbF9maW5hbDIwMDkxNV9fZ2VuZW5hbWUuY3N2IikgIzE5MTIwNiDov73liqAKCm5yb3cobm9ybV9wbG90bGlzdF9hbGwpCm5yb3cobm9ybV9wbG90bGlzdF9hbGxfbmFtZSkKCmBgYAoKCm5vcm1fcGxvdGxpc3RfYWxsICJOb3JtX2RlZnRhYmxlX2FsbF9maW5hbDIwMDkxNS5jc3YiIOOCkuS9v+OBhgoKYGBge3Igbm9ybWNvdW50LCBmaWcud2lkdGg9MTIsZmlnLmhlaWdodD05fQoKcGxvdGdlbmVfbGlzdCA8LSBjKCJDb2wzYTEiLCJBY3RhMSIsIk15b2ciLCJNeW9kMSIsIlRubnQxIiwiVG5udDIiLCJUbm50MyIsIkNzcnAzIiwiTXloMyIsIkNrbSIsIlJwbDI3IiwiQWN0YiIsIkdhcGRoIiwiU2xjMzhhMiIsIkluaGJhIiwiTXloOSIsIlJwbDEzIiwiTnNkaGwiKQpsZW5ndGgocGxvdGdlbmVfbGlzdCkKCiMiTXloMyIsIkNrbSIsIkFjdGExIiwiVG5udDIiLCJBY3RiIiwiQ3NycDMiCgpyZSAlPiUgZmlsdGVyKGFzcGVjdD09Imdyb3VwX0Q3Ml9tbTE4Ql92c19lR0ZQIikgJT4lIGZpbHRlcihleHRfZ2VuZSAlaW4lIHBsb3RnZW5lX2xpc3QpICU+JSBhcnJhbmdlKGxvZzJGb2xkQ2hhbmdlKQoKIz09PT09PT09IENoYW5nZSBldmVyeSBkYXRhIOOBk+OBk+OBp+mghueVquOCkuWkieabtCA9PT09PT09PSMKCiMtLS0tLS0tIwoKbmJsIDwtIG5vcm1fcGxvdGxpc3RfYWxsX25hbWUgJT4lIGZpbHRlcihleHRfZ2VuZSAlaW4lIHBsb3RnZW5lX2xpc3QpCgojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSMKCmZfZ2VuZV9ub3JtIDwtIGZ1bmN0aW9uKHgpIHggJT4lIGdyb3VwX2J5KGdyb3VwLCB0eXBlLCB0aW1lLCBleHRfZ2VuZSkgJT4lIHN1bW1hcmlzZShhdmc9bWVhbihub3JtYWxpemVkKSxzZT1zZChub3JtYWxpemVkKS9zcXJ0KGxlbmd0aChub3JtYWxpemVkKSkpICU+JSB1bmdyb3VwKCkKCiMtLS0tIwpuYmwgJT4lIGdyb3VwX2J5KGdyb3VwLCB0eXBlLCB0aW1lKSAlPiUgc3VtbWFyaXNlKCkKIy0tLS0jCgojZmFjZT0iaXRhbGljIgojLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpICNY6Lu444Gu44Op44OZ44Or44KS5YK+44GR44KL5aC05ZCICiMsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSAjWOi7uOOBruODqeODmeODq+OCkuawtOW5s+OBq+OBmeOCi+WgtOWQiAoKIyMjIHBvaW50ICMjIwpnZ2dnZ3BwIDwtICBnZ3Bsb3QobmJsLGFlcyh0aW1lLG5vcm1hbGl6ZWQsZ3JvdXA9dHlwZSxjb2xvdXI9dHlwZSkpK2dlb21fcG9pbnQoc2l6ZT0yKStmYWNldF93cmFwKH5leHRfZ2VuZSxzY2FsZT0iZnJlZV95Iixucm93PTMpK2dlb21fbGluZShzaXplPTEuMCwgYWVzKHg9dGltZSx5PWF2Zyxjb2xvdXI9dHlwZSksZGF0YT1mX2dlbmVfbm9ybSkrdGhlbWVfYncoKSArIHlsaW0oMCxOQSkgKyB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF90ZXh0KGhqdXN0ID0gMSwgc2l6ZT0xNiksIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNiksYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MjAsZmFjZT0iaXRhbGljIiksIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNikpK2dnc2NpOjpzY2FsZV9jb2xvcl9ucGcoKSAgKyB5bGFiKCJub3JtYWxpemVkIGNvdW50IikKCmZpbGVfcGF0aCA8LSAiLi9ub3JtQ291bnQvbm9ybUNvdW50X3Bsb3RfZmluYWwyMDA5MTVfcGxvdDEucGRmIgpwcmludChmaWxlX3BhdGgpCmdnc2F2ZShmaWxlPWZpbGVfcGF0aCwgcGxvdCA9IGdnZ2dncHAsIGRwaSA9IDEwMCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gMTApCgpwcmludChnZ2dnZ3BwKQoKCmdnZ2dncHAgPC0gIGdncGxvdChuYmwsYWVzKHRpbWUsbm9ybWFsaXplZCxncm91cD10eXBlLGNvbG91cj10eXBlKSkrZ2VvbV9wb2ludChzaXplPTIpK2ZhY2V0X3dyYXAofmV4dF9nZW5lLHNjYWxlPSJmcmVlX3kiLG5yb3c9MykrZ2VvbV9zbW9vdGgoc2U9RkFMU0UpK3RoZW1lX2J3KCkgKyB5bGltKDAsTkEpICsgdGhlbWUoYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChoanVzdCA9IDEsIHNpemU9MTYpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpLGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE2KSwgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplPTIwLGZhY2U9Iml0YWxpYyIpLCBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTYpKStnZ3NjaTo6c2NhbGVfY29sb3JfbnBnKCkgICsgeWxhYigibm9ybWFsaXplZCBjb3VudCIpCgpmaWxlX3BhdGggPC0gIi4vbm9ybUNvdW50L25vcm1Db3VudF9wbG90X2ZpbmFsMjAwOTE1X3Bsb3QxX3Ntb290aC5wZGYiCnByaW50KGZpbGVfcGF0aCkKZ2dzYXZlKGZpbGU9ZmlsZV9wYXRoLCBwbG90ID0gZ2dnZ2dwcCwgZHBpID0gMTAwLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA5KQoKCmBgYAoKCiMjIyBUUE0KClRQTeOBp+S9nOWbsyAoMTkxMjAz5L+u5q2jKQoKYGBge3IgVFBNIE1hdG9tZSBkZWYgMTkwNzIyLTEyMDN9CiMg44Kr44Km44Oz44OIMOOCguihqOekuuOBmeOCi+OCiOOBhuOBq+WkieabtCAoMjAxOTA3MjIpCgp0cG0gPC0gdW1pICU+JSBncm91cF9ieShzYW1wbGUpICU+JSBtdXRhdGUoc2FtcGxlX3RvdGFsPXN1bShjb3VudCksVFBNPWNvdW50L3N1bShjb3VudCkqMWU2KSAlPiUgdW5ncm91cAp0cG1femVybyA8LSB0cG0gJT4lIHNlbGVjdChzYW1wbGUsZW5zX2dlbmUsVFBNKSAlPiUgc3ByZWFkKHNhbXBsZSxUUE0sZmlsbD0wKSAlPiUgZ2F0aGVyKHNhbXBsZSwgVFBNLCAtZW5zX2dlbmUpICPjgqvjgqbjg7Pjg4gw44Gu44K144Oz44OX44Or44GvMOOCkuWFpeOCjOOCiyAyMDE5MDcyMui/veWKoOOBl+OBpuS/ruatowoKdHBtX2RlZiA8LSBkZWYgJT4lIHNlbGVjdCgtY291bnQpICU+JSBkcGx5cjo6aW5uZXJfam9pbih0cG1femVybywgYnkgPSAic2FtcGxlIikgI3RwbeOCknRwbV96ZXJv44Gr5L+u5q2j44CBMjAxOTA3MjLkv67mraMKCm1hdG9tZSA8LSB0cG1fZGVmICU+JSBpbm5lcl9qb2luKGUyZywgYnkgPSAiZW5zX2dlbmUiKQoKcmVhZHI6OndyaXRlX2NzdihtYXRvbWUsIkl3YXNha2lfMDM4NnJlX0MyQzEyX0gzbW0xOF91bWlfVFBNX19maW5hbDIwOTE1LmNzdiIpICMxOTEyMDMg6L+95YqgCgojLS0g56K66KqNIC0tIwp1bWkgJT4lIGdyb3VwX2J5KHNhbXBsZSkgJT4lIHN1bW1hcmlzZShzdW0oY291bnQpKSAjIOeiuuiqjQp0cG1femVybyAlPiUgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgc3VtbWFyaXNlKHN1bShUUE0pKSAjIOeiuuiqjQpoZWFkKG1hdG9tZSkKCiMtLSDopprmm7ggLS0jCiN0cG0gJT4lIGZpbHRlcihlbnNfZ2VuZT09IkVOU01VU0cwMDAwMDA0MzA5MCIpICMxN+WAiwojdHBtX3plcm8gJT4lIGZpbHRlcihlbnNfZ2VuZT09IkVOU01VU0cwMDAwMDA0MzA5MCIpICMzMuWAiwoKIyAtLSDml6d2ZXIgLS0tCiN0cG0gPC0gdW1pICU+JSBncm91cF9ieShzYW1wbGUpICU+JSBtdXRhdGUoc2FtcGxlX3RvdGFsPXN1bShjb3VudCksVFBNPWNvdW50L3N1bShjb3VudCkqMWU2KSAlPiUgdW5ncm91cAojdW1pICU+JSBncm91cF9ieShzYW1wbGUpICU+JSBzdW1tYXJpc2Uoc3VtKGNvdW50KSkKI3RwbSAlPiUgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgc3VtbWFyaXNlKHN1bShUUE0pKQojdHBtX2RlZiA8LSBkZWYgJT4lIHNlbGVjdCgtY291bnQpICU+JSBkcGx5cjo6aW5uZXJfam9pbih0cG0sIGJ5ID0gInNhbXBsZSIpCgpgYGAKCgoK